向已关闭的 channel 发送数据会 panic。Go 语言中,对已 close() 的 channel 执行发送操作(ch
Go 语言中,对一个已经 close() 的 channel 执行发送操作(ch )会立即触发运行时 panic,错误信息为 panic: send on closed channel。这属于不可恢复的致命错误,程序会崩溃,除非被 recover() 捕获——但通常不建议这么做。
channel 关闭语义明确:关闭表示“不再有新值要发”,是生产端的终结信号。接收端可通过 v, ok := 中的 ok 判断是否已关闭;而发送端若还能继续发,就违背了该契约。因此 Go 选择在编译期无法检查的场景下,用运行时 panic 强制暴露逻辑错误。
典型出错模式是:多个 goroutine 并发写 channel,其中一个关闭后,其余仍尝试发送;或在 select + default 分支中未检查 channel 状态就盲目发送。
done chan struct{} 配合 select
go test -race 检测潜在的并发关闭/发送竞争package mainimport "fmt"
func main() { ch := make(chan int, 1) close(ch) ch <- 42 // panic: send on closed channel fmt.Println("unreachable") }
注意:即使 channel 带缓冲且仍有空位,只要已关闭,任何发送都会 panic。缓冲区只影响阻塞行为,不改变关闭后的语义约束。
真正难处理的不是 panic 本身,而是它往往出现在多 goroutine 协作的边界上——那个“谁该关、何时关、关完谁负责”的责任划分,比语法细节更易出错。