
Go 语言中使用 channel 进行跨 goroutine 通信时,若接收端仅执行一次
go 语言中使用 channel 进行跨 goroutine 通信时,若接收端仅执行一次 `
在您提供的代码中,Websock 函数仅执行了一次
func Websock(ws *websocket.Conn) {
msg := <p>这导致函数在收到第一条消息后立即退出,websocket.Conn 随之被关闭(Go 的 http 服务在 handler 返回后自动关闭连接),后续写入 messages channel 的消息无人消费,造成“只能收到一条消息”的现象。</p><p>✅ 正确做法是:在 Websock 中启动一个<strong>持续接收循环</strong>,并配合 defer ws.Close() 确保资源释放:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/learn/7564" title="使用Go语言搭建家庭相册系统-相关课件"><img
src="https://img.php.cn/upload/webcode/000/000/164/636a2b4d84031727.png" alt="使用Go语言搭建家庭相册系统-相关课件" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/learn/7564" title="使用Go语言搭建家庭相册系统-相关课件" class="overflowclass">使用Go语言搭建家庭相册系统-相关课件</a>
<p class="overflowclass">使用Go语言搭建家庭相册系统-相关课件</p>
</div>
<a rel="nofollow" href="/xiazai/learn/7564" title="使用Go语言搭建家庭相册系统-相关课件" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><pre class="brush:php;toolbar:false;">func Websock(ws *websocket.Conn) {
defer ws.Close() // 确保连接最终关闭
for {
select {
case msg := <p>⚠️ 注意事项:</p>
- messages 是无缓冲 channel(make(chan string)),若接收端未及时读取,发送端会在第二次 messages 永久阻塞(如您的 ExampleNewWatcher goroutine 中)。虽然当前因 watcher.Events 循环仍在运行,但逻辑上已不可靠。
- 建议为 messages 添加合理缓冲(如 make(chan string, 16)),避免生产者因消费者延迟而卡死。
- ExampleNewWatcher 中 defer watcher.Close() 写法错误(多了一个 0),应为 defer watcher.Close();且 done := make(chan bool) 未被关闭或写入,导致
- 若需支持多个客户端同时监听同一事件流,应考虑为每个 WebSocket 连接单独复制消息(如使用 fan-out 模式 + sync.Map 管理 client channels),而非共享单一全局 channel。
总结:channel 是 Go 并发通信的基石,但“一次接收 ≠ 持续监听”。任何需要长期响应消息的 handler(尤其是网络连接场景),都必须显式编写接收循环,并妥善处理错误与连接生命周期。










