
Go 中使用 channel 实现事件通知时,若接收端仅执行一次
go 中使用 channel 实现事件通知时,若接收端仅执行一次 `
在您的代码中,Websock 函数仅执行了一次 msg :=
✅ 正确做法是:在 Websock 中启动一个持续监听循环,并确保 WebSocket 连接保持打开状态,直到客户端断开或发生错误:
func Websock(ws *websocket.Conn) {
// 启动 goroutine 持续发送消息,避免阻塞主协程
go func() {
defer ws.Close() // 确保连接最终关闭
for {
select {
case msg := <p>⚠️ 注意事项:</p>
- 通道类型与缓冲:当前 messages = make(chan string) 是无缓冲通道,发送方会在无接收者就绪时永久阻塞。建议根据并发压力设置合理缓冲容量(如 make(chan string, 10)),避免 watcher 协程卡死。
- 资源泄漏风险:每个 WebSocket 连接都启动独立 goroutine 监听 messages,若未做连接数限制或超时控制,可能引发 goroutine 泄漏。生产环境应结合 context 或连接池管理。
- 并发安全:多个 Websock 实例共享同一 messages 通道,属于广播模式(所有连接均收到相同消息)。如需定向推送,请改用 map[*websocket.Conn]chan string + 逐个分发。
- Watcher 生命周期:ExampleNewWatcher 中 defer watcher.Close() 在函数返回时才调用,但该函数本身是 goroutine,且 done 通道未被关闭,实际不会触发 Close()。应显式管理 watcher 生命周期,或改用 sync.WaitGroup 协调。
总结:通道不是“消息队列服务”,而是 Go 的同步/通信原语;要实现持续消息消费,接收端必须主动循环 select 或 for range(仅适用于已关闭的 channel)。WebSocket 场景下,务必让接收逻辑与连接生命周期对齐——以 goroutine + 循环 + 错误退出为核心范式。











