不要在消费端关闭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