Golang WebSocket广播核心是channel消息中枢与goroutine并发分发,需确保读写分离、连接安全、异常清理;用sync.RWMutex保护clients map,设WriteDeadline防慢连接,recover捕获写错并清理连接。

在Golang中实现WebSocket广播,核心是用channel做消息中枢、用goroutine做并发分发,避免阻塞主线程。关键不在“写多少代码”,而在于读写分离、连接安全、异常清理这三点是否到位。
定义广播通道与客户端集合
声明一个全局的broadcast channel,类型为chan []byte或自定义消息结构体,所有客户端发来的消息都先投递到这里。同时维护一个并发安全的客户端集合:
- 用
map[*websocket.Conn]bool记录活跃连接 - 用
sync.RWMutex保护读写,注册/注销时加写锁,广播遍历时加读锁 - 避免直接用
sync.Mutex——读多写少场景下RWMutex能显著提升吞吐
启动独立广播协程
服务启动时就go handleBroadcast(),让它持续监听broadcast channel:
- 收到消息后,先加读锁遍历clients map
- 对每个连接调用
conn.WriteMessage(websocket.TextMessage, msg) - 务必设置
conn.SetWriteDeadline(time.Now().Add(5 * time.Second)),防止慢连接拖垮整个广播 - 写失败时recover捕获panic,关闭该conn并从map中移除
每个连接配两个协程:读+写分离
新连接升级成功后,立即启动两个goroutine:
立即学习“go语言免费学习笔记(深入)”;
-
读协程:循环
conn.ReadMessage(),把原始消息(或解析后的结构体)推入broadcastchannel -
写协程:可选——如果需要向特定用户单播或做消息过滤,可为每个client分配独立
send chan []byte,由该协程消费并写出 - 读出错或连接关闭时,触发注销流程:向
unregisterchannel发信号,或直接加锁删除map条目
前端连接与消息收发很简单
浏览器端只需几行JavaScript:
const ws = new WebSocket("ws://localhost:8000/ws")ws.onmessage = e => console.log("收到:", e.data)-
ws.send("你好")即可触发后端广播 - 建议加
onerror和onclose处理断连重试逻辑
基本上就这些。不复杂但容易忽略write deadline、panic恢复和map清理——这三个点没做好,上线后扛不住几十个并发就会卡死或内存暴涨。










