Golang 服务端推送消息首选 WebSocket 实现双向实时通信,需用 gorilla/websocket 库升级 HTTP 连接、构建 Hub 管理连接及 goroutine 收发消息;SSE 则适用于单向推送,通过设置响应头、按 data: 格式推送并维护客户端 channel 实现。

在 Golang 中实现服务端推送消息,核心是建立一种服务器能主动向客户端发送数据的通信机制。HTTP 协议本身是请求 - 响应模式,无法满足实时性要求,因此需要采用长连接技术。目前最主流和高效的方法是使用 WebSocket,它支持全双工通信,允许服务端随时推送消息。Server-Sent Events(SSE)是另一种轻量级方案,适用于只需要服务端单向推送的场景。
使用 WebSocket 进行双向实时推送
WebSocket 是实现实时应用的首选技术,特别适合聊天室、在线游戏或需要双向交互的系统。
- 引入依赖库 :Go 标准库不包含 WebSocket 支持,推荐使用成熟的第三方库github.com/gorilla/websocket。通过
go get github.com/gorilla/websocket安装。 - 升级 HTTP 连接 :服务端监听一个特定路径(如 /ws),当收到客户端的 Upgrade 请求时,使用Upgrader.Upgrade() 方法将普通的 HTTP 连接转换为持久的 WebSocket 连接。记得设置
CheckOrigin: func(r *http.Request) bool {return true}以处理跨域问题(生产环境需更严格校验)。 - 管理客户端连接:为避免并发读写 map 导致的 panic,设计一个中心化的“Hub”或管理器。它通常包含一个存储所有活跃连接的 map、一个用于注册 / 注销连接的通道(chan)、以及一个用于广播消息的通道。通过一个 for-select 循环在主线程中安全地处理这些操作。
- 处理消息收发 :每个新连接都启动两个独立的 goroutine。一个负责readPump,持续调用
conn.ReadMessage()监听客户端发来的消息,并将其转发到广播通道。另一个负责 writePump,从广播通道接收消息,然后调用conn.WriteMessage()推送给对应的客户端。
使用 SSE 实现服务端单向消息推送
如果应用场景只需要服务端向客户端推送通知或状态更新(如股票行情、新闻推送),SSE 是一个更简单优雅的选择,它基于 HTTP 协议,天然兼容性好。
- 建立 SSE 连接:客户端通过 JavaScript 的EventSource API 发起请求。服务端接收到请求后,首先设置关键的响应头:
Content-Type: text/event-stream、Cache-Control: no-cache和Connection: keep-alive,以保持长连接并禁用缓存。 - 推送数据格式 :服务端推送的数据必须遵循事件流格式。每次发送数据时,以
data:开头,后跟实际内容,最后以nn结束。例如:fmt.Fprintf(c.Writer, "data: %snn", message)。发送后立即调用c.Writer.Flush()强制将数据刷到客户端,而不是等待缓冲区满。 - 管理客户端列表 :与 WebSocket 类似,需要一个全局的 map 来存储所有活跃的 SSE 客户端。但由于 SSE 是单向的,客户端列表中的元素通常是带缓冲的 channel(如
chan string)。当有新消息要广播时,遍历这个 map,将消息发送到每个客户端的 channel 中。同时,在处理 SSE 路由 的函数里,通过for msg := range clientChan监听该 channel,并将收到的消息按 SSE 格式写回响应。 - 触发推送:可以提供一个独立的 HTTP 接口(如 POST /send),接收要推送的内容,然后由服务端逻辑将此内容发送到所有客户端的 channel 中,从而触发对所有连接的广播。
基本上就这些。选择 WebSocket 还是 SSE 取决于具体需求。WebSocket 功能强大但相对复杂;SSE 实现简单,专精于服务端推送。对于简单的通知类应用,SSE 往往是更优解。






























