我想写一个worker,它每隔1个小时做一次工作。目前我们的系统中还没有cron,所以不想增加cron。请求在后续的实现中提出建议。
func init(){
go startWorker()
}
func startWorker(){
doJob()
time.Sleep(time.Second * 3600)
}
在go例程中使用sleep是个坏主意吗? 或者有什么更好的选择来做这些事情?doJob()
是为了从DB中获取过去一小时内发生的所有故障,并进行重试。
有两个问题,在使用 time.Sleep
以你设想的方式,一主一辅。
goroutine被卡在一个无限循环中,所以除非 doJob
恐慌,它永远不会终止。 你可能应该给它传递一个通道,当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
}
}
}
或者,更好的是,使用ticker:
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资源可以忽略不计,但它却使用了一个堆栈,大约有十几千字节。 这对你来说可能不是一个问题,但如果是这样,而且如果你的应用程序有一个主循环,那么你可以插入你的 ticker 和调用的 doWork
入主 select
主循环的语句。