Skip to content

time api

定时器

  • time.After
  • time.NewTimer
  • time.Ticker

time.After

go
select {
case <-time.After(2 * time.Second):
	fmt.Println("timeout")
}

time.NewTimer

Timer(一次)

go
timer := time.NewTimer(3 * time.Second)
<-timer.C
fmt.Println("fired")

timer.C 是一个 <-chan time.Time

NewTimer 可停止,可重置,内存可控。

go
t := time.NewTimer(5 * time.Second)

stopped := t.Stop()

// stopped : true 成功
// stopped : flase 已经触发或已停止
go
t := time.NewTimer(2 * time.Second)

t.Reset(5 * time.Second)

解决“残留信号”问题

go
if !t.Stop() {
    <-t.C
}
t.Reset(d)

goroutine 泄漏

go
timer := time.NewTimer(timeout)
defer timer.Stop()

for {
    select {
    case <-timer.C:
        // 超时处理
        timer.Reset(timeout)

    case msg := <-ch:
        if !timer.Stop() {
            <-timer.C
        }
        timer.Reset(timeout)
        _ = msg
    }
}

todo: 超时自动关闭的 worker

time.NewTicker

Ticker(周期/反复触发)

go
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()

for {
	<-ticker.C
	fmt.Println("tick")
}
go
ticker.Stop() // 停止
ticker.Reset(newDuration) // 重新开始,并且设置新的 周期
// newDuration是必须的!newDuration是必须的!newDuration是必须的!
// newDuration不能为零值!newDuration不能为零值!newDuration不能为零值!
// 零值会一直打印、零值会一直打印、零值会一直打印

time.Tick

go
c := time.Tick(200 * time.Millisecond)
for t := range c {
    fmt.Println("tick at", t)
}

返回一个 <-chan Time

每隔指定间隔往 c 里发送一个 time.Time