Golang: Library: Ticker

 11th October 2021 at 2:45pm

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 直接被跳过。