把 channel 設成 nil 可以停用 select 的某個 case
nil channel 永遠 block。 這個看似沒用的性質有一個漂亮的用途:把 channel 變數設成
nil,那個 case 就等於被動態關掉了。
用途在於:channel 被 close 之後不會再 block,反而會一直回傳零值——如果不處理,那個 case 會瘋狂空轉。
for fast != nil || slow != nil { // 兩根都關掉才離開
select {
case msg, ok := <-fast:
if !ok {
fast = nil // ← 停用這個 case,不再被選中
fmt.Println("fast channel closed")
continue
}
fmt.Println("received:", msg)
case msg, ok := <-slow:
if !ok {
slow = nil
continue
}
fmt.Println("received:", msg)
}
}三個零件合起來才成立:
msg, ok := <-ch的ok為false代表 channel 已被close(跟 map 的 comma ok 是同一個語法家族)- 把該變數設成
nil→ nil channel 永遠 block → select 永遠不會選中它 - 迴圈條件用
!= nil判斷「還有沒有活著的來源」
沒有這招的話,得另外維護一組布林旗標來記錄「哪些來源結束了」,還要在每個 case 裡判斷。用 nil 直接讓 select 自己忽略它,是 Go 並行程式碼裡常見的慣用法。
相關:Channel 是 goroutine 之間的通訊管道、select 是 channel 版的 switch、nil map 可以讀但不能寫