为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
繁华开满天机 2023-03-07 14:02:16
由于我不是经验丰富的 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 的内部工作原理吗?
查看完整描述

2 回答

?
慕码人8056858

TA贡献1803条经验 获得超6个赞

http.ListenAndServe(":8080", nil)运行一个无限for循环监听入站连接,这就是为什么如果你之后调用它,代码不会被调用的原因。


然后在这里


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

time.Sleep(60 * time.Second)

close(done)

ticker.Stop()

您将在 60 秒后退出内部循环schedule(),因此您的自动收报机将只运行一次或根本不会运行(取决于完成通道是在自动收报机运行之前还是之后收到值,因为它们是并发的,我们无法确定他们的订单)


所以你想要的是以下内容


func main() {

    http.HandleFunc("/data", headers)


    ticker := time.NewTicker(time.Minute)

    go schedule(ticker)


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

    http.ListenAndServe(":8080", nil)

}


func schedule(ticker *time.Ticker) {

    for {

        // This blocks until a value is received, the ticker

        // sends a value to it every one minute (or the interval specified)

        <-ticker.C

        fmt.Println("Tick")

    }

}

您可能已经注意到,一旦服务器连接中断,程序就会终止,因此没有必要使用通道done来退出循环。


查看完整回答
反对 回复 2023-03-07
?
梵蒂冈之花

TA贡献1900条经验 获得超5个赞

您走在正确的轨道上——您只需要将代码声明包装在一个自执行函数中,然后将其作为 goroutine 运行。ListenAndServe并且Schedule都是阻塞任务,因此它们需要在单独的 go 例程上运行。幸运的是,go 使这很容易实现。


注意 - 此示例代码旨在尽可能接近您的示例。我建议将代码的声明与计划函数分开。


func main() {


    http.HandleFunc("/data", func(w http.ResponseWriter, req *http.Request) {}) //line 1


    var done chan bool


    go func() {

        ticker := schedule(func() { fmt.Println("Tick") }, time.Second, done)

        time.Sleep(60 * time.Second)

        close(done)

        ticker.Stop()

    }()


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

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

}


查看完整回答
反对 回复 2023-03-07
  • 2 回答
  • 0 关注
  • 72 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信