如何在Golang中实现WebSocket消息广播_推送给多个客户端

Golang WebSocket广播需安全维护连接集合并异步分发消息:用sync.RWMutex保护clients map,快照连接切片广播;通过broadcast channel解耦收发,设写 deadline、recover异常、启心跳检测失效连接。

在Golang中实现WebSocket消息广播,核心是**安全维护在线连接集合 + 异步分发消息**。不依赖第三方服务,用标准库配合 gorilla/websocket 就能稳定支撑百至千级并发。

管理客户端连接:用 map + 读写锁保障并发安全

所有活跃连接必须集中存储,并确保多协程读写不冲突:

  • 声明 clients map[*websocket.Conn]bool 存储当前连接
  • sync.RWMutex 包裹增删操作(如新连接加入、断开时删除)
  • 升级HTTP连接后立即注册:clients[conn] = true,并在 defer 中清理
  • 避免直接遍历原始 map —— 广播前先用 RLock() 快照一份连接切片,防止遍历时被修改

广播消息:通过 channel 解耦接收与发送

不让读消息的协程直接遍历连接,否则一个慢连接会拖垮所有人:

  • 定义全局 broadcast chan []byte 作为消息中转站
  • 启动独立 goroutine 持续监听该 channel:for msg := range broadcast { ... }
  • 每次收到消息,遍历快照连接列表,调用 conn.WriteMessage(websocket.TextMessage, msg)
  • 为每个写操作设置 conn.SetWriteDeadline(time.Now().Add(10 * time.Second)),防阻塞

处理异常连接:自动识别并清理失效连接

客户端断网、关页、超时都是常态,不能靠等待 Close 通知:

  • WriteMessage 外加 recover(),捕获 panic(如连接已关闭)
  • 检查错误是否为 websocket.ErrCloseSentio.EOF,是则立即 conn.Close() 并从 clients 中删除
  • 启用心跳机制:每 30 秒发一次 ping,客户端需回 pong;超时未响应则主动断开
  • 读协程里用 conn.SetReadDeadline 配合 conn.ReadMessage,超时即视为离线

前端配合:简单可靠即可完成闭环

浏览器端无需复杂逻辑,原生 WebSocket API 足够:

  • 创建连接:const ws = new WebSocket("ws://localhost:8080/ws")
  • 发送消息:ws.send(JSON.stringify({type:"msg", content:"hello"}))
  • 接收广播:ws.onmessage = e => console.log("收到:", JSON.parse(e.data))
  • 重连建议:监听 onclose,延迟 1–3 秒后尝试重建连接