Golang 实现实时聊天需用 WebSocket 替代 HTTP 轮询,核心是连接管理、消息分发和并发安全;通过 gorilla/websocket 升级连接,Hub 中心化管理客户端、广播消息,readPump/writePump 双 goroutine 解耦收发,前端用 ws 协议连接并处理收发与重连。

用 Golang 实现实时聊天功能,核心是用 WebSocket 替代 HTTP 轮询,让服务端能主动推消息给 前端。关键不在写多少代码,而在理清连接管理、消息分发和并发安全这三块。
用 gorilla/websocket 升级 HTTP 连接
WebSocket 不是新协议,而是通过 HTTP“握手”升级来的。Golang 原生不支持,得靠第三方库:
- 执行 go get github.com/gorilla/websocket 安装依赖
- 定义 Upgrader 并放开 跨域(开发可设
CheckOrigin: func(r *http.Request) bool {return true},上线必须限制) - 在 HTTP路由 里调用
upgrader.Upgrade(w, r, nil),成功就拿到*websocket.Conn实例 - 每个连接建议立刻启动两个 goroutine:一个
readPump收消息,一个writePump发消息,避免阻塞
设计中心化 Hub 管理所有连接
没有统一管理者,广播就无从谈起。Hub 不是可选模块,而是必建结构:
- 定义
type Hub struct {clients map[*Client]bool; broadcast chan []byte; register, unregister chan *Client} -
clients存活跃连接,用指针作 key 更稳妥;broadcast是 字节 流通道,所有要群发的消息都往里塞 -
register/unregister是控制通道,Hub 主循环用select监听它们,保证增删 map 的操作串行,避开并发读写 panic - 启动
hub.Run()作为后台 goroutine,它不退出,一直协调消息流转
客户端收发与消息广播逻辑
每个 Client 对象封装连接和发送通道,消息流是单向解耦的:
立即学习“go 语言免费学习笔记(深入)”;
- 用户发消息 →
readPump解析 JSON(含 username、message、time)→ 写入hub.broadcast -
hub.Run()从broadcast取到消息 → 遍历clients→ 对每个 Client 的send通道发一份 -
writePump监听自己 Client 的send通道 → 调用conn.WriteMessage()推给 浏览器 - 断开连接时,先关
send通道,再从clients删除,最后conn.Close()
前端配合要点
后端 再稳,前端连不上也白搭:
- 用
new WebSocket("ws://localhost:8080/ws")建立连接,注意协议是ws或wss,不是http - 监听
onmessage接收 JSON 字符串,JSON.parse()后更新 DOM - 发送时构造
{username: "A", message: "hello"},再ws.send(JSON.stringify(……)) - 加
onerror和onclose处理异常断线,必要时自动重连






























