如何使用Golang实现简易聊天室_使用WebSocket进行消息通信

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

用 Golang 实现一个简易聊天室,核心是用 WebSocket 做实时双向通信,而不是轮询或 HTTP 短连接。关键不在代码行数,而在结构清晰、并发安全、消息不丢。

WebSocket 服务端搭建

先引入 gorilla/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 重试