--- description: Go WebSocket 服务开发规范 globs: ["**/*.go"] alwaysApply: true --- # Go WebSocket 服务开发核心规范 ## 1. 技术选型与库使用 - **首选库**: 本项目统一使用 `github.com/gorilla/websocket` 库来处理 WebSocket 连接。 - **禁止使用**: 除非有特殊理由,请**避免**直接使用标准库 `golang.org/x/net/websocket`,因为它缺少一些高级功能和性能优化。 ## 2. WebSocket 连接处理 - **Upgrader 配置**: - 必须创建一个全局或可重用的 `websocket.Upgrader` 实例。 - `CheckOrigin` 函数**必须**实现,用于校验请求来源,防止跨站 WebSocket 劫持 (CSWSH)。在开发环境中可以暂时允许所有来源,但在生产环境中必须严格校验。 ```go var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool { // TODO: 在生产环境中替换为你的域名白名单 // return r.Header.Get("Origin") == "[https://yourdomain.com](https://yourdomain.com)" return true // 开发环境 }, } ``` - **连接升级**: 在 HTTP Handler 中,使用 `upgrader.Upgrade(w, r, nil)` 来将会话升级为 WebSocket 连接。务必妥善处理该过程中的 `error`。 - **并发安全**: `websocket.Conn` 对象**不是**并发安全的。对同一个连接的写操作必须在单一的 goroutine 中进行。通常的设计模式是为每个连接启动两个 goroutine:一个用于读(`ReadMessage`),一个用于写。 ## 3. 设计模式与代码结构 - **核心结构体**: - **Client/Connection**: 创建一个结构体来封装 `*websocket.Conn`,并包含其他与客户端相关的状态,如用户ID、订阅的频道等。 ```go type Client struct { conn *websocket.Conn send chan []byte // 用于发送消息的缓冲 channel // 其他用户标识... userID string } ``` - **Hub/Manager**: 创建一个中心化的管理器,用于处理客户端的注册、注销和消息广播。 ```go type Hub struct { clients map[*Client]bool broadcast chan []byte register chan *Client unregister chan *Client } ``` - **读写分离**: - **读 Goroutine (`readPump`)**: - 在一个 `for` 循环中持续调用 `conn.ReadMessage()`。 - 在此 goroutine 中处理连接关闭和错误。当 `ReadMessage` 返回错误时,意味着客户端已断开,应执行清理逻辑(如调用 `hub.unregister`)。 - 设置 Pong 消息处理器,用于维持心跳。 - 设置读超时 `conn.SetReadDeadline()`。 - **写 Goroutine (`writePump`)**: - 从 `Client` 的 `send` channel 中读取消息。 - 在一个 `for` 循环中使用 `conn.WriteMessage()` 发送消息。 - 设置 Ping 消息,定期发送以检测连接活性。 - 设置写超时 `conn.SetWriteDeadline()`。 ## 4. 消息格式 - **统一格式**: 所有客户端与服务端之间的消息都应使用 JSON 格式。 - **消息结构**: 定义一个标准的消息结构体,包含消息类型、荷载 (payload) 等字段,以便于路由和处理。 ```go type WebSocketMessage struct { Type string `json:"type"` Payload interface{} `json:"payload"` }