前言
在業務中,我們經常需要基於定時任務來觸發來實現各種功能。比如ttl會話管理、鎖、定時任務(鬧鐘)或更複雜的狀態切換等等。百納網主要給大家介紹了關於golang定時器陷阱的相關內容,所謂陷阱,就是它不是你認為的那樣,這種認知誤差可能讓你的軟體留下隱藏bug。剛好timer就有3個陷阱,我們會講
1)reset的陷阱和
2)通道的陷阱,
3)stop的陷阱與reset的陷阱類似,自己探索吧。
下面話不多說了,來一起看看詳細的介紹吧
reset的陷阱在哪
timer.reset()函式的返回值是bool型別,我們看乙個問題三連:
成功:一段時間之後定時www.cppcns.com器超時,收到超時事件。
失敗:成功的反面,我們收不到那個事件。對於失敗,我們應當做些什麼,確保我們的定時器發揮作用。
reset的返回值是不是這個意思?
通過檢視文件和實現,timer.reset()的返回值並不符合我們的預期,這就是誤差。它的返回值不代表重設定時器成功或失敗,而是在表達定時器在重設前的狀態:
所以,當reset返回false時,我們並不能認為一段時間之後,超時不會到來,實際上可能會到來,定時器已經生效了。
跳過陷阱,再遇陷阱
如何跳過前面的陷阱,讓reset符合我們的預期功能呢?直接忽視reset的返回值好了,它不能幫助你達到預期的效果。
真正的陷阱是timer的通道,它和我們預期的成功、失敗密切相關。我們所期望的定時器設定失敗,通常只和通道有關:設定定時器前,定時器的通道timer.c中是否已經有資料。
接下來解釋為何失敗只與通道中是否存在超時事件有關。
定時器的快取通道大小只為1,無法多存放超時事件,看原始碼。
// newtimer creates a new timer that will send
// the cuwww.cppcns.comrrent time on its channel after at least duration d.
func newtimer(d duration) *timer ,
} starttimer(&t.r)
return t
}定時器建立後是單獨執行的,超時後會向通道寫入資料,你從通道中把資料讀走。當前一次的超時資料沒有被讀取,而設定了新的定時器,然後去通道讀資料,結果讀到的是上次超時的超時事件,看似成功,實則失敗,完全掉入陷阱。
跨越陷阱,確保成功
如果確保timer.reset()成功,得到我們想要的結果?timer.reset()前清空通道。
當業務場景簡單時,沒有必要主動清空通道。比如,處理流程是:設定1次定時器,處理一次定時器,中間無中斷,下次reset前,通道必然是空的。
當業務場景複雜時,不確定通道是否為空,那就主動清除。
if len(timer.c) > 0 else
// 停止timer
tm.stop()
if !tm.reset(time.second) else
// timer超時
for else
fmt.printf("reset後通道中事件的數量:%d\n", len(tm2.c))
select {
case t := 0 {
總結本文標題: golang中定時器的陷阱詳解
本文位址:
golang中的定時器
type timer struct乙個定時器,代表未來的乙個單一事件,你可以告訴timer你要等待多長時間,它提供乙個channel,在將來的那個時間channel提供了乙個時間值 time.newtimer時間到了,只響應一次 func main time.after 2 time.second ...
golang定時器實現
golang定時器,需求是能夠在指定時間後停止。或某種條件出發停止。好,下面上貨。package main import context fmt sync time func main func stoptheworld func goclock for func goclock2 執行結果 123...
golang定時器和超時的使用詳解
我就廢話不多說了,大家還是直接看 吧 func main func senddatato a chan string 在一定時間內接收不到a的資料則超時 func getachan timeout time.duration,a chan string 補充 golang的定時器newtimer n...