用Golang基于gorilla/websocket实现简易聊天室,通过hub goroutine+channel管理并发安全的连接与广播,读写分离为readPump/writePump两个goroutine,支持跨域、断开清理和前端原生WebSocket接入。

用 Golang 实现一个简易聊天室,核心是用 WebSocket 做实时双向通信,而不是轮询或 HTTP 短连接。关键不在代码行数,而在结构清晰、并发安全、消息不丢。
WebSocket 服务端搭建
go get github.com/gorilla/websocket
创建 HTTP 路由,把 /ws 路径升级为 WebSocket 连接:
- 定义 Upgrader 并设置 CheckOrigin 允许跨域(开发阶段可设为 true)
- 在 handler 中调用 upgrader.Upgrade() 完成协议切换
- 每个成功连接的 *websocket.Conn 就代表一个在线用户
客户端连接与广播管理
不能直接用全局 map 存连接并随意读写——Go 的 map 不支持并发安全操作。需要配合 channel 和 sync 包来协调:
- 用 map[*websocket.Conn]bool 记录活跃连接,但只在专用 goroutine 中增删
- 设一个 broadcast channel(如 chan []byte 或自定义 Message 结构),所有客户端发来的消息都往里塞
- 启动一个长期运行的 hub goroutine,监听 broadcast,收到消息后遍历 clients 广播出去
- 客户端断开时,主动从 map 删除,并关闭其 send channel,避免 goroutine 泄漏
收发分离:每个连接配两个 goroutine
单个连接既要读消息又要发消息,阻塞式调用会卡死。标准做法是拆开:
- readPump:循环调用 conn.ReadMessage(),解析后转成结构体,再发到 broadcast channel
- writePump:从专属的 client.send channel 取消息,调用 conn.WriteMessage() 推送
- 这样读写互不干扰,还能对不同用户做差异化推送(比如私聊、房间隔离)
前端接入很简单
浏览器原生支持 WebSocket,不用额外库:
- 用 new WebSocket("ws://localhost:8080/ws") 建连
- 监听 onmessage 渲染消息到页面,滚动到底部保持最新
- 输入框回车或点击发送时,调用 ws.send(JSON.stringify({username, body}))
- 建议加简单重连逻辑,比如 onclose 后 setTimeout 重试










