time 包中有一个 Ticker 功能,可以定时触发一个 channel:
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(500 * time.Millisecond)
done := make(chan bool)
go func() {
for {
select {
case <-done:
return
case t := <-ticker.C:
fmt.Println("Tick at", t)
}
}
}()
time.Sleep(1600 * time.Millisecond)
ticker.Stop()
done <- true
fmt.Println("Ticker stopped")
}
如果 receiver 的代码逻辑太慢,ticker 会自动跳过中间的时间间隔。比如这样的代码:
package main
import (
"fmt"
"time"
)
func main() {
timeLayout := "15:04:05"
ticker := time.NewTicker(3 * time.Second)
done := make(chan bool)
go func() {
for {
select {
case <-done:
return
case t := <-ticker.C:
fmt.Printf("Tick time %v, current time %v\n", t.Format(timeLayout), time.Now().Format(timeLayout))
time.Sleep(4 * time.Second)
}
}
}()
time.Sleep(1000 * time.Second)
ticker.Stop()
done <- true
fmt.Println("Ticker stopped")
}
由于消费 ticker 的函数的执行时间(4s)大于 ticker 的间隔(3s),其中有几次 tick 会被跳过。实际执行的输出如:
Tick time 14:42:43, current time 14:42:43
Tick time 14:42:46, current time 14:42:47
Tick time 14:42:49, current time 14:42:51
Tick time 14:42:52, current time 14:42:55
Tick time 14:42:58, current time 14:42:59
Tick time 14:43:01, current time 14:43:03
Tick time 14:43:04, current time 14:43:07
Tick time 14:43:10, current time 14:43:11
注意 14:42:55 本来应该有一次 tick,但是因为消费 ticker 的时间是 59s,当时已经有更新的 tick 产生了,因此旧的 tick 直接被跳过。