2 回答

TA貢獻1874條經驗 獲得超12個贊
例如,假設程序尚未從 tC 接收到:
if !t.Stop() {
? ? ? ? <-t.C
}
這不能與來自計時器通道的其他接收同時完成。
有人可能會說這不是一個很好的例子,因為它假設計時器在您調用時正在運行t.Stop
。但它確實繼續提到,如果已經有一些現有的 Goroutine 正在或可能正在讀取t.C
.
(Reset
文檔重復了所有這些,并且順序有點錯誤,因為Reset
排序在 之前Stop
。)
本質上,整個地區都有點令人擔憂。沒有好的通用答案,因為在返回t.Stop
呼叫期間至少存在三種可能的情況:
沒有人正在收聽該頻道,并且頻道中現在沒有定時器滴答聲。如果計時器在調用之前
t.Stop
已停止,通常會出現這種情況。如果計時器已經停止,t.Stop
則始終返回 false。沒有人正在收聽該頻道,并且頻道中現在有計時器滴答聲。當計時器正在運行但
t.Stop
無法阻止其觸發時,總是會出現這種情況。在這種情況下,t.Stop
返回 false。當計時器正在運行但在您調用之前t.Stop
就觸發了,因此它自己停止了,所以t.Stop
無法停止它并返回 false。其他人正在收聽該頻道。
在最后一種情況下,您不應該執行任何操作。在第一種情況下,您不應該執行任何操作。在第二種情況下,您可能希望從通道接收以便將其清除。這就是他們的例子的目的。
有人可能會爭辯說:
if !t.Stop() {
? ? ? ? select {
? ? ? ? case <-t.C:
? ? ? ? default:
? ? ? ? }
}
是一個更好的例子。它執行一次非阻塞嘗試,該嘗試將消耗計時器滴答(如果存在),如果沒有計時器滴答,則不執行任何操作。無論您調用 時計時器是否實際運行,這都有效t.Stop。事實上,如果t.Stopreturns ,它甚至可以工作true,盡管在這種情況下,t.Stop停止了計時器,因此計時器從未設法將計時器滴答放入通道中。(因此,如果通道中存在數據,則它必然是先前清除通道失敗所遺留的。如果不存在此類錯誤,則嘗試接收也就不必要了。)
但是,如果其他人(其他一些 goroutine)正在或可能正在讀取該通道,那么您根本不應該執行此操作。盡管調用了 ,但無法知道誰(您或他們)將獲得通道中可能存在的任何計時器滴答聲Stop。
同時,如果您不打算進一步使用計時器,那么在通道中留下一個計時器滴答聲(如果有的話)相對無害。當通道本身被垃圾收集時,它也會被垃圾收集。當然,這是否明智取決于您對計時器所做的事情,但在這些情況下,只需調用t.Stop并忽略其返回值就足夠了。

TA貢獻1951條經驗 獲得超3個贊
您創建一個計時器并立即停止它:
var?tmr?=?time.NewTimer(time.Second) tmr.Stop()
這沒有任何意義,我認為這只是你的“意外”。
但更進一步,在循環內部:
????case?_,?ok?:=?<-watcher.Events:
當發生這種情況時,您聲稱這不起作用:
????????if?!tmr.Stop()?{ ????????????fmt.Println(`Ticker:?CHAN?DRAIN`) ????????????<-tmr.C?//?STOPS?HERE?AND?GOES?NO?FURTHER ????????}
Timer.Stop()
記錄true
如果此調用停止計時器以及false
計時器已停止(或到期)則返回。但是你的計時器在創建后就已經停止了,所以正確tmr.Stop()
返回false
,所以你進入if
并嘗試從 接收tmr.C
,但由于計時器“長時間”停止,因此不會在其通道上發送任何內容,因此這是一個阻塞(永遠)操作。
如果您是使用 顯式停止計時器的人timer.Stop()
,則推薦的用于耗盡其通道的“模式”沒有任何意義,并且不適用于第二次調用Timer.Stop()
。
- 2 回答
- 0 關注
- 351 瀏覽
添加回答
舉報