有没有办法在Golang中间隔地执行重复任务?

Go有没有办法做重复的后台任务? 我正在考虑像Timer.schedule(task, delay, period) 。 我知道我可以用goroutine和Time.sleep()来做到这一点,但是我想要一些容易停下来的东西。

这是我得到的,但看起来很丑。 有更清洁/更好的方法吗?

 func oneWay() { var f func() var t *time.Timer f = func () { fmt.Println("doing stuff") t = time.AfterFunc(time.Duration(5) * time.Second, f) } t = time.AfterFunc(time.Duration(5) * time.Second, f) defer t.Stop() //simulate doing stuff time.Sleep(time.Minute) } 

函数time.NewTicker创build一个发送周期性消息的通道,并提供一种停止的方法。 使用它像这样(未经testing):

 ticker := time.NewTicker(5 * time.Second) quit := make(chan struct{}) go func() { for { select { case <- ticker.C: // do stuff case <- quit: ticker.Stop() return } } }() 

您可以通过closuresquit渠道来停止员工: close(quit)

感觉如何?

 package main import ( "fmt" "time" ) func schedule(what func(), delay time.Duration) chan bool { stop := make(chan bool) go func() { for { what() select { case <-time.After(delay): case <-stop: return } } }() return stop } func main() { ping := func() { fmt.Println("#") } stop := schedule(ping, 5*time.Millisecond) time.Sleep(25 * time.Millisecond) stop <- true time.Sleep(25 * time.Millisecond) fmt.Println("Done") } 

操场

看看这个库: https : //github.com/robfig/cron

示例如下:

 c := cron.New() c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") }) c.AddFunc("@hourly", func() { fmt.Println("Every hour") }) c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") }) c.Start() 

如果您不关心打勾转移(取决于以前每次执行需要多长时间)并且您不想使用通道,则可以使用本地范围function。

 package main import "fmt" import "time" func main() { go heartBeat() time.Sleep(time.Second * 5) } func heartBeat(){ for range time.Tick(time.Second *1){ fmt.Println("Foo") } } 

操场

对这个问题的更广泛的回答可能会考虑经常在Occam中使用的Lego砖方法,并通过JCSP提供给Java社区。 彼得·韦尔奇(Peter Welch)就这个想法做了很好的介绍 。

这种即插即用的方法直接转换为Go,因为Go使用与Occam相同的通信顺序过程基础。

因此,在devise重复任务时,可以将系统构build为一个简单组件的数据streamnetworking(如goroutine),通过通道交换事件(即消息或信号)。

这种方法是组合性的:每个小组件组本身可以performance为一个更大的组件,无限的。 这可以是非常强大的,因为复杂的并发系统是由易于理解的砖块制成的。

脚注:在Welch的演讲中,他使用Occam语法来表示频道,这是 这些直接对应于Go中的ch < –<-ch