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 關注
- 129 瀏覽
添加回答
舉報