general_rules.mdc 3.3 KB

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