Go 是如何按时间间隔调用 Ticker 的?

由于我不是经验丰富的 Go 开发人员,所以我不了解使用 Ticker 的方式。我有以下情况:


一个在特定端口 8080 上运行的 go web 服务,它从另一个应用程序获取数据并处理数据。到目前为止一切顺利,但我在此 Web 服务中有另一个sendData功能,它循环遍历一些文件并将它们发送到另一个外部服务。我试图sendData()每 1 分钟调用一次该函数。下面是没有 Tickers 时 main 函数的样子:


func main() {


    http.HandleFunc("/data", headers)          //line 1

    log.Printf("Ready for data ...%s\n", 8080) //line 2

    http.ListenAndServe(":8080", nil)          //line 3

}


line 2如果我在无限循环后添加 Ticker 。如果我在之后添加line 3,程序不会调用 Ticker。知道如何处理这个吗?


代码部分


ticker := schedule(sendData, time.Second, done)

time.Sleep(60 * time.Second)

close(done)

ticker.Stop()

和时间表从


func schedule(f func(), interval time.Duration, done <-chan bool) *time.Ticker {

    ticker := time.NewTicker(interval)

    go func() {

        for {

            select {

            case <-ticker.C:

                f()

            case <-done:

                return

            }

        }

    }()

    return ticker

所以基本上我想在每分钟或每小时等时发送数据。有人可以解释 Ticker 的内部工作原理吗?


繁华开满天机
浏览 77回答 2
2回答

慕码人8056858

http.ListenAndServe(":8080", nil)运行一个无限for循环监听入站连接,这就是为什么如果你之后调用它,代码不会被调用的原因。然后在这里ticker := schedule(sendData, time.Second, done)time.Sleep(60 * time.Second)close(done)ticker.Stop()您将在 60 秒后退出内部循环schedule(),因此您的自动收报机将只运行一次或根本不会运行(取决于完成通道是在自动收报机运行之前还是之后收到值,因为它们是并发的,我们无法确定他们的订单)所以你想要的是以下内容func main() {&nbsp; &nbsp; http.HandleFunc("/data", headers)&nbsp; &nbsp; ticker := time.NewTicker(time.Minute)&nbsp; &nbsp; go schedule(ticker)&nbsp; &nbsp; log.Printf("Ready for data ...%s\n", 8080)&nbsp; &nbsp; http.ListenAndServe(":8080", nil)}func schedule(ticker *time.Ticker) {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; // This blocks until a value is received, the ticker&nbsp; &nbsp; &nbsp; &nbsp; // sends a value to it every one minute (or the interval specified)&nbsp; &nbsp; &nbsp; &nbsp; <-ticker.C&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Tick")&nbsp; &nbsp; }}您可能已经注意到,一旦服务器连接中断,程序就会终止,因此没有必要使用通道done来退出循环。

梵蒂冈之花

您走在正确的轨道上——您只需要将代码声明包装在一个自执行函数中,然后将其作为 goroutine 运行。ListenAndServe并且Schedule都是阻塞任务,因此它们需要在单独的 go 例程上运行。幸运的是,go 使这很容易实现。注意 - 此示例代码旨在尽可能接近您的示例。我建议将代码的声明与计划函数分开。func main() {&nbsp; &nbsp; http.HandleFunc("/data", func(w http.ResponseWriter, req *http.Request) {}) //line 1&nbsp; &nbsp; var done chan bool&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; ticker := schedule(func() { fmt.Println("Tick") }, time.Second, done)&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(60 * time.Second)&nbsp; &nbsp; &nbsp; &nbsp; close(done)&nbsp; &nbsp; &nbsp; &nbsp; ticker.Stop()&nbsp; &nbsp; }()&nbsp; &nbsp; fmt.Printf("Ready for data ...%v\n", 8080) //line 2&nbsp; &nbsp; http.ListenAndServe(":8080", nil)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //line 3}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go