不要在消費端關閉channel,不要在有多個並行的生產者時對channel執行關閉操做。
也就是說應該只在[惟一的或者最後惟一剩下]的生產者協程中關閉channel,來通知消費者已經沒有值能夠繼續讀了。只要堅持這個原則,就能夠確保向一個已經關閉的channel發送數據的狀況不可能發生。golang
若是想要在消費端關閉channel,或者在多個生產者端關閉channel,可使用recover機制來上個保險,避免程序由於panic而崩潰。併發
func SafeClose(ch chan T) (justClosed bool) { defer func() { if recover() != nil { justClosed = false } }() close(ch) return true }
使用這種方法明顯違背了上面的channel關閉原則,而後性能還能夠,畢竟在每一個協程只會調用一次SafeClose,性能損失很小。
一樣也能夠在生產消息的時候使用recover方法。
性能
還有很多人常常使用sync.Once來關閉channel,這樣能夠確保只會關閉一次
設計
一樣咱們也可使用sync.Mutex達到一樣的目的。
要知道golang的設計者不提供SafeClose或者SafeSend方法是有緣由的,
他們原本就不推薦在消費端或者在併發的多個生產端關閉channel,
好比關閉只讀channel在語法上就完全被禁止使用了。3d
就上面這個例子,生產者同時也是退出信號channel的接受者,退出信號channel仍然是由它的生產者code