我正在尝试设置一个每小时运行的服务例程。在我看来,这两个都很容易。要按小时运行我的例程,我可以使用 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 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/