Go语言如何通过时间间隔调用Ticker?

pgccezyw  于 2022-12-07  发布在  Go
关注(0)|答案(2)|浏览(107)

由于我不是一个有经验的围棋开发者,我不明白如何使用Ticker。我有以下的场景:
一个运行在特定端口8080上的go web服务,它从另一个应用程序获取数据并处理数据。到目前为止一切都很好,但我在这个web服务中有另一个sendData函数,它循环通过一些文件并将它们发送到另一个外部服务。我尝试每隔1分钟调用一次sendData()函数。下面是主函数在没有标记的情况下的外观:

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。您知道如何处理这个问题吗?
股票代码部分

ticker := schedule(sendData, time.Second, done)
time.Sleep(60 * time.Second)
close(done)
ticker.Stop()

schedule from之间的关系

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

因此,基本上我想发送数据evert分钟或小时等。有人能解释内部Ticker如何工作吗?

qjp7pelc

qjp7pelc1#

http.ListenAndServe(":8080", nil)运行一个无限的for循环来侦听入站连接,这就是为什么如果您以后调用它,不会调用ticker。
然后这里

ticker := schedule(sendData, time.Second, done)
time.Sleep(60 * time.Second)
close(done)
ticker.Stop()

60秒后退出schedule()内部的循环,因此您的ticker将只运行一次或根本不运行(取决于done通道是在ticker滴答之前还是之后接收到值,因为它们是并发的,我们无法确定它们的顺序)
所以你需要的是

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通道退出循环。
Try it here

jaxagkaj

jaxagkaj2#

你的思路是正确的--你只需要把代码声明封装在一个自执行函数中,然后把它作为goroutine运行。ListenAndServeSchedule都是阻塞任务,所以它们需要在单独的go例程上运行,幸运的是go使这一点变得非常简单。

  • 注意-这个示例代码是为了尽可能接近您的示例。我建议将代码的声明与schedule函数分开。*
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
}

相关问题