Go Time包中的NewTimer()和After()函式

LiberHome發表於2022-06-01

    標準庫的Timer允許使用者自定義超時邏輯(適用於單個chanel讀寫超時、select處理多個chanel超時等情況)。

  • 注意:Timer是一次性觸發,和一定時間間隔觸發的Ticker不同(類似JavaScript裡的settimeout和setinterval的區別)。

Timer常見的建立方式如下:

  • t := time.NewTimer(d)
  • t := time.AfterFunc(d, f)
  • c := time.After(d)
    (注:d代表定時時間;f代表觸發的動作;c就是chanel)

time.NewTimer

舉個實際例子來說明這個API的用法:

package main

import (
    "fmt"
    "time"
)

func main() {
    timer := time.NewTimer(3 * time.Second)
    fmt.Printf("%T\n", timer)
    //列印一下系統的當前時間
    fmt.Println(time.Now())
    //此處等待chanel中的數值 會阻塞3s
    ch2 := timer.C
    fmt.Println(<-ch2)
}

執行結果如下:

*time.Timer
2022-05-27 18:15:59.740761 +0800 CST m=+0.000224834
2022-05-27 18:16:02.741175 +0800 CST m=+3.000731959

另外 在計時器到期之前我們還可以取消這個計時器,比如下面的程式碼例子:

package main

import (
    "fmt"
    "time"
)

func main() {
    //    新建一個計時器
    timer2 := time.NewTimer(5 * time.Second)
    //開始協程處理觸發後的事件
    go func() {
        <-timer2.C
        fmt.Println("timer2 has been completed")
    }()

    time.Sleep(3 * time.Second)
    flag := timer2.Stop()
    if flag {
        fmt.Println("Timer2 was stopped")
    }
}

執行結果是:
Timer2 was stopped

time.After()

本質上就是NewTimer(d).C,作用就是在持續時間d之後返回通道C,C中儲存的是d後的時間。
func After(d Duration) <- chan Time
注:如果有效率問題需要考慮,官方文件建議使用NewTimer來替代。 如果當前計時器不被需要了,也可以用Stop()停止。

參考:bilibili

相關文章