波斯汪
使用 atime.Ticker定期接收“事件”,您可以使用它来为函数的执行计时。time.Ticker您可以通过致电获得time.NewTicker()。返回的代码有一个定期发送值的通道。使用 goroutine 连续接收事件并调用函数,例如使用循环for range。让我们看看 2 个函数:func oneSec() { log.Println("oneSec")}func twoSec() { log.Println("twoSec")}这是一个定期调用给定函数的简单调度程序:func schedule(f func(), interval time.Duration) *time.Ticker { ticker := time.NewTicker(interval) go func() { for range ticker.C { f() } }() return ticker}使用它的例子:func main() { t1 := schedule(oneSec, time.Second) t2 := schedule(twoSec, 2*time.Second) time.Sleep(5 * time.Second) t1.Stop() t2.Stop()}示例输出(在Go Playground上尝试):2009/11/10 23:00:01 oneSec2009/11/10 23:00:02 twoSec2009/11/10 23:00:02 oneSec2009/11/10 23:00:03 oneSec2009/11/10 23:00:04 twoSec2009/11/10 23:00:04 oneSec请注意,Ticker.Stop()不会关闭代码通道,因此 afor range不会终止;Stop()仅停止在代码通道上发送值。如果您想终止用于安排函数调用的 goroutine,您可以使用额外的通道来完成。然后那些 goroutines 可能会使用一个select语句来“监控”ticker 的频道和这个done频道,如果从中接收done成功则返回。例如:func schedule(f func(), interval time.Duration, done <-chan bool) *time.Ticker { ticker := time.NewTicker(interval) go func() { for { select { case <-ticker.C: f() case <-done: return } } }() return ticker}并使用它:func main() { done := make(chan bool) t1 := schedule(oneSec, time.Second, done) t2 := schedule(twoSec, 2*time.Second, done) time.Sleep(5 * time.Second) close(done) t1.Stop() t2.Stop()}请注意,即使在这个简单的示例中没有必要停止代码(因为当maingoroutine 结束时,程序也会结束),在现实生活中,如果应用程序继续运行,让代码不停止会浪费资源(它们会继续使用后台 goroutine,并将继续尝试在他们的频道上发送值)。最后的话:如果您有一段函数区间对,只需使用循环将每一对传递给此schedule()函数即可。是这样的:type pair struct { f func() interval time.Duration}pairs := []pair{ {oneSec, time.Second}, {twoSec, 2 * time.Second},}done := make(chan bool)ts := make([]*time.Ticker, len(pairs))for i, p := range pairs { ts[i] = schedule(p.f, p.interval, done)}time.Sleep(5 * time.Second)close(done)for _, t := range ts { t.Stop()}