1 回答
TA贡献1811条经验 获得超4个赞
使用 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 oneSec
2009/11/10 23:00:02 twoSec
2009/11/10 23:00:02 oneSec
2009/11/10 23:00:03 oneSec
2009/11/10 23:00:04 twoSec
2009/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()
}
请注意,即使在这个简单的示例中没有必要停止代码(因为当main
goroutine 结束时,程序也会结束),在现实生活中,如果应用程序继续运行,让代码不停止会浪费资源(它们会继续使用后台 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()
}
- 1 回答
- 0 关注
- 96 浏览
添加回答
举报