
在 go 中,若需向多个 goroutine 广播“初始化完成”信号且仅触发一次,直接向无缓冲通道发送单个值会导致后续接收者阻塞;正确做法是关闭通道——所有接收操作会立即返回零值并继续执行,从而安全实现多点同步。
在 go 中,若需向多个 goroutine 广播“初始化完成”信号且仅触发一次,直接向无缓冲通道发送单个值会导致后续接收者阻塞;正确做法是关闭通道——所有接收操作会立即返回零值并继续执行,从而安全实现多点同步。
在 Go 并发编程中,使用通道(channel)进行同步是一种常见模式。但初学者常误以为“发送一个值”即可满足多处等待需求,而忽略了通道的语义本质:每个 操作必须对应一个 <code>ch (或通道关闭)才能返回。若只发送一次值却有多个接收方,首个接收者成功后,其余将永久阻塞,最终引发 fatal error: all goroutines are asleep - deadlock!。
上述问题的根本解法是:用 close(ch) 替代 ch 。因为对已关闭的只读通道执行接收操作,会立即返回该类型的零值(bool 的零值为 false),且 ok 为 true(表示接收成功),这恰好构成清晰的“就绪信号”语义。
以下是修正后的完整示例:
package main import "fmt" // done 通过关闭通道广播就绪信号 func done(ok chan<p><strong>运行输出:</strong></p><pre class="brush:php;toolbar:false;">✅ One waiter is ready ✅ One waiter is ready All Ok!
✅ 关键要点总结:
-
关闭通道 = 广播事件:
close(ch)是 Go 中实现“单次广播、多方接收”的标准惯用法; -
接收已关闭通道安全:
立即返回零值 + <code>false(第二个返回值),可用于判断是否收到关闭通知; -
无需缓冲或额外值:相比
make(chan bool, 1)+ch ,关闭方式更简洁、无内存占用、语义更明确; -
注意并发安全:确保只有一个 goroutine 调用
close(),多次关闭会 panic; - 适用场景:服务启动就绪、配置加载完成、资源初始化完毕等“一次性全局状态通知”。
此模式被广泛应用于标准库(如 net/http.Server.Shutdown)、Kubernetes 客户端及各类 Go 框架中,是 Go 并发同步的基石实践之一。










