应使用 gorilla/websocket 的 Upgrader.Upgrade() 启动服务禁用手动 HTTP 响应读写需分离 goroutine用 ReadMessage/WriteMessage 处理消息设读写超时连接断开时主动清理资源。用 gorilla/websocket 启动一个基础服务别碰 net/http 原生实现Go 官方 net/http 没有 WebSocket 支持硬写握手和帧解析极易出错。直接上 gorilla/websocket——它不是“第三方可选”而是事实标准。它的 Upgrader 封装了所有协议细节包括 Origin 校验、Sec-WebSocket-Key 生成、HTTP 状态码响应你只需专注业务逻辑。常见错误自己用 http.ResponseWriter 写 101 Switching Protocols漏掉 Connection: upgrade 或 Upgrade: websocket 头浏览器报 WebSocket connection to xxx failed。必须用 Upgrader.Upgrade()不能手动写响应头Upgrader.CheckOrigin 默认拒绝非同源请求开发时设为 func(r *http.Request) bool { return true }上线前务必改回严格校验每个连接要单独起 goroutine 处理读/写避免阻塞其他连接读消息时用 conn.ReadMessage()别循环调 conn.Read()ReadMessage() 自动处理 WebSocket 帧解包、掩码解密、碎片重组而 Read() 是底层字节流操作需手动解析 FIN、opcode、mask、payload length —— 极易因边界判断错误导致 panic 或丢数据。典型现象前端发一条文本消息后端收到空字符串或乱码日志里出现 websocket: bad write message type 或 unexpected EOF。立即学习“go语言免费学习笔记深入”ReadMessage() 返回 messageType, data, errormessageType 通常是 websocket.TextMessage 或 websocket.BinaryMessage不要在同一个 goroutine 里连续调 ReadMessage() 和 WriteMessage()可能触发并发写 panic读写应分离到不同 goroutine或加锁超时控制用 conn.SetReadDeadline()不是靠 time.After 包裹读操作写消息必须用 conn.WriteMessage()且注意 WriteDeadlineWriteMessage() 负责帧封装、掩码服务端不掩码但函数内部会忽略、缓冲区管理。手动拼帧或用 Write() 写原始字节大概率触发 websocket: close sent 或连接静默断开。 Mokker AI AI产品图添加背景