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处理异常断线,必要时自动重连










