我想写一个每工作1小时要说一次的 worker 。截至目前,我们的系统中没有Cron,因此不想添加cron。在后续实现中提出建议:
func init(){
go startWorker()
}
func startWorker(){
doJob()
time.Sleep(time.Second * 3600)
}
在日常工作中使用 sleep 是个坏主意,还是有更好的选择来做这样的事情。
doJob()
的工作是从数据库中获取最近一个小时内发生的所有故障,然后重试
最佳答案
按照您的设想使用time.Sleep
有两个问题,一个主要和一个次要。
您无法终止goroutine
goroutine陷入无限循环,因此,除非doJob
出现 panic ,否则它将永远不会终止。您可能应该向它传递一个 channel ,该 channel 在goroutine需要终止时将被关闭:
done := make(chan struct{})
go worker(done)
...
close(done)
...
func worker(done <-chan struct{}){
for {
doJob()
timer := time.NewTimer(time.Hour)
select {
case <-timer.C:
// nothing
case <-done:
timer.Stop()
return
}
}
}
或者,更好的是,使用代码:
func worker(done <-chan struct{}){
ticker := time.NewTicker(time.Hour)
for {
doJob()
select {
case <-ticker.C:
// nothing
case <-done:
ticker.Stop
return
}
}
}
这是使用
defer
的好样式:func worker(done <-chan struct{}){
ticker := time.NewTicker(time.Hour)
defer ticker.Stop()
for {
doJob()
select {
case <-ticker.C:
// nothing
case <-done:
return
}
}
}
你在浪费堆栈
当goroutine使用微不足道的CPU资源时,它使用的堆栈大约为十几千字节。对于您来说,这可能不是问题,但如果是这样,并且如果您的应用程序具有主循环,则可以将代码和
doWork
的调用插入到主循环的主select
语句中。
关于go - 有没有更好的选择去使用常规 sleep ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62159498/