1 回答

TA貢獻(xiàn)1834條經(jīng)驗 獲得超8個贊
select
沒有 case 的語句是default
阻塞的case
,直到可以執(zhí)行至少一個語句中的讀取或?qū)懭搿R虼?,?code>select將阻塞,直到可以從通道讀取quit
(如果通道關(guān)閉,則為值或零值)。語言規(guī)范提供了對此行為的具體描述,特別是:
如果一個或多個通信[在陳述中表達(dá)
case
]可以繼續(xù),則通過統(tǒng)一的偽隨機(jī)選擇選擇一個可以繼續(xù)的通信。否則,如果存在默認(rèn)情況,則選擇該情況。如果沒有默認(rèn)情況,則“select”語句將阻塞,直到至少有一個通信可以繼續(xù)進(jìn)行。
其他代碼問題
警告!break
適用于select
聲明
但是,即使您確實關(guān)閉了quit
通道以發(fā)出關(guān)閉程序的信號,您的實施也可能不會產(chǎn)生預(yù)期的效果。對 的(未標(biāo)記的)調(diào)用break
將終止函數(shù)內(nèi)最內(nèi)層的for
orselect
語句switch
的執(zhí)行。在這種情況下,select
語句將中斷,for
循環(huán)將再次運(yùn)行。如果quit
被關(guān)閉,它將永遠(yuǎn)運(yùn)行直到其他東西停止程序,否則它將再次阻塞select
關(guān)閉quit
將(可能)不會立即停止程序
正如time.Sleep
所指出的,在循環(huán)的每次迭代中調(diào)用都會阻塞一秒鐘,因此任何通過關(guān)閉來停止程序的嘗試都會在 goroutine 檢查和退出quit
之前延遲大約一秒鐘。quit
在程序停止之前,這個睡眠周期不太可能必須完全完成。
更慣用的 Go 會在select
從兩個渠道接收的語句中阻塞:
頻道
quit
_返回的通道
time.After
– 此調(diào)用是圍繞 a 的抽象Timer
,它會休眠一段時間,然后將值寫入提供的通道。
解決
更改最少的解決方案
通過對代碼進(jìn)行最少更改來解決您的直接問題的解決方案是:
通過向語句添加默認(rèn)情況,使讀取成為
quit
非阻塞的select
。確保 goroutine在讀取成功時實際
quit
返回:標(biāo)記
for
循環(huán)并使用標(biāo)記調(diào)用break
;?或者return
f1
在需要退出時從函數(shù)中獲?。ㄊ走x)
根據(jù)您的情況,您可能會發(fā)現(xiàn) Go 更慣用地使用 a 來context.Context
發(fā)出終止信號,并使用 async.WaitGroup
等待 goroutine 在從 返回之前完成main
。
package main
import (
? ? "fmt"
? ? "time"
)
func f1(quit chan bool) {
? ? go func() {
? ? ? ? for {
? ? ? ? ? ? println("f1 is working...")
? ? ? ? ? ? time.Sleep(1 * time.Second)
? ? ? ? ? ? select {
? ? ? ? ? ? case <-quit:
? ? ? ? ? ? ? ? fmt.Println("stopping")
? ? ? ? ? ? ? ? return
? ? ? ? ? ? default:
? ? ? ? ? ? }
? ? ? ? }
? ? }()
}
func main() {
? ? quit := make(chan bool)
? ? f1(quit)
? ? time.Sleep(4 * time.Second)
? ? close(quit)
? ? time.Sleep(4 * time.Second)
}
工作示例
(注意:我在您的方法中添加了一個額外的time.Sleep
調(diào)用main
,以避免在調(diào)用close
和終止程序后立即返回。)
修復(fù)睡眠阻塞問題
要解決有關(guān)阻止立即退出的阻塞睡眠的其他問題,請將睡眠移動到塊中的計時器select
。for
根據(jù)這個游樂場示例修改循環(huán)正是這樣做的:
for {
? ? println("f1 is working...")
? ? select {
? ? case <-quit:
? ? ? ? println("stopping f1")
? ? ? ? return
? ? case <-time.After(1 * time.Second):
? ? ? ? // repeats loop
? ? }
}
- 1 回答
- 0 關(guān)注
- 142 瀏覽
添加回答
舉報