go - 首先等待 time.AfterFunc 然后启动 time.NewTicker

标签 go

我正在尝试设置一个每小时运行的服务例程。在我看来,这两个都很容易。要按小时运行我的例程,我可以使用 time.AfterFunc() ,首先计算到整点的剩余时间。为了每小时运行我的例程,我可以使用 time.NewTicker() .

但是,我正在努力弄清楚如何启动 NewTicker仅在函数传递给 AfterFunc() 之后已解雇。

我的main()函数看起来像这样:

func main() {
    fmt.Println("starting up")

    // Here I'm setting up all kinds of HTTP listeners and gRPC listeners, none
    // of which is important, save to mention that the app has more happening
    // than just this service routine.

    // Calculate duration until next hour and call time.AfterFunc()
    // For the purposes of this exercise I'm just using 5 seconds so as not to
    // have to wait increments of hours to see the results
    time.AfterFunc(time.Second * 5, func() {
        fmt.Println("AfterFunc")
    })

    // Set up a ticker to run every hour. Again, for the purposes of this
    // exercise I'm ticking every 2 seconds just to see some results
    t := time.NewTicker(time.Second * 2)
    defer t.Stop()
    go func() {
        for now := range t.C {
            fmt.Println("Ticker")
        }
    }()

    // Block until termination signal is received
    osSignals := make(chan os.Signal, 1)
    signal.Notify(osSignals, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
    <-osSignals

    fmt.Println("exiting gracefully")
}

当然time.AfterFunc()正在阻塞,我的 Ticker 的有效负载被故意放入 go 例程中,因此它也不会被阻塞。这样我的 HTTP 和 gRPC 监听器可以继续监听,但也允许 main() 末尾的代码块根据操作系统发出的终止信号优雅退出。但现在明显的缺点是Ticker在函数传递到 AfterFunc() 之前几乎立即开始并触发两次(间隔 2 秒)火灾。输出如下所示:

Ticker
Ticker
AfterFunc
Ticker
Ticker
Ticker
etc.

我想要的当然是:

AfterFunc
Ticker
Ticker
Ticker
Ticker
Ticker
etc.

以下内容也不起作用,我不确定为什么。它打印 AfterFunc 但 Ticker 从不触发。

time.AfterFunc(time.Second * 5, func() {
        fmt.Println("AfterFunc")

        t := time.NewTicker(time.Second * 2)
        defer t.Stop()
        go func() {
            for now := range t.C {
                fmt.Println("Ticker")
            }
        }()
    })

最佳答案

The Go Programming Language Specification

Program execution

Program execution begins by initializing the main package and then invoking the function main. When that function invocation returns, the program exits. It does not wait for other (non-main) goroutines to complete.

time.AfterFunc(time.Second * 5, func() {
    fmt.Println("AfterFunc")
    t := time.NewTicker(time.Second * 2)
    defer t.Stop()
    go func() {
        for now := range t.C {
            fmt.Println("Ticker")
        }
    }()
})

defer t.Stop() 停止股票代码。

你没有等待 goroutine 运行。

关于go - 首先等待 time.AfterFunc 然后启动 time.NewTicker,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57543721/

相关文章:

go - 为结构动态设置键和值

go - 在golang中将数组值设置为结构

unicode - 字符串文字和字符串值之间的区别?

amazon-web-services - 如何通过全局二级索引过滤golang中的dynamodb?

arrays - 如何将 Go 结构的一部分定义为 JSON 字符串?

postgresql - PostgreSQL Has-Many关系插入相同的ID错误

string - 如何从字符串中的给定日期找到工作日?

go - 如何列出和复制非字母数字字符的 s3 key ?

string - 如何从字符串中删除二进制内容?

Go 函数类型作为接口(interface)值