三种会 panic 的操作:向已关闭的 channel 发送;重复关闭同一个 channel(close 两次);关闭 nil channel。另外向 nil channel 发送或从 nil channel 接收是永久阻塞而非 panic,这个特性常被用于 select 中动态禁用某个分支。
从已关闭 channel 接收不会 panic:立即返回零值,第二个返回值 ok 为 false,且缓冲里残留的数据仍可被取完。正确姿势的核心原则是:由发送方负责关闭,接收方永远不关;多个发送者时不能直接 close,需用 sync.Once、额外的退出信号 channel,或由唯一协调者关闭。
// 多发送者:用独立 quit 信号而不是 close 数据 channel
func worker(quit <-chan struct{}, out chan<- int) {
for {
select {
case <-quit:
return
case out <- compute():
}
}
}
易错点:close 是广播,所有接收方都收到关闭事件,适合'通知大家退出';用 close 传递最后一个业务值是误用。追问方向:for range 消费 channel 的退出条件、or-done 模式。