
Go 中使用 golang.org/x/net/websocket 无法直接发送带状态码和原因的关闭消息;需改用更现代的 Gorilla WebSocket 库,通过 FormatCloseMessage 构造关闭帧,并先写入再调用 Close() 实现符合标准的带消息关闭。
go 中使用 `golang.org/x/net/websocket` 无法直接发送带状态码和原因的关闭消息;需改用更现代的 gorilla websocket 库,通过 `formatclosemessage` 构造关闭帧,并先写入再调用 `close()` 实现符合标准的带消息关闭。
WebSocket 协议(RFC 6455)规定:关闭连接时可携带一个 2 字节的状态码(如 1000 表示正常关闭)及 UTF-8 编码的可选原因文本(最长 123 字节)。浏览器 JavaScript 端可通过 event.code 和 event.reason 获取该信息:
websocket.onclose = function(event) {
console.log('Code:', event.code); // e.g., 1000
console.log('Reason:', event.reason); // e.g., "Server shutdown"
console.log('WasClean:', event.wasClean); // true if closed gracefully
};但 golang.org/x/net/websocket(已归档、不再维护)的 Close() 方法不支持传入参数,无法发送自定义关闭消息。因此,强烈建议迁移到功能完备、广泛使用的 Gorilla WebSocket(导入路径:github.com/gorilla/websocket)。
以下是使用 Gorilla WebSocket 发送带消息关闭帧的正确方式:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
import (
"log"
"github.com/gorilla/websocket"
)
// 假设 ws 是 *websocket.Conn 类型的连接
func closeWithMessage(ws *websocket.Conn, code int, reason string) error {
// 构造标准关闭消息帧(自动处理字节序和长度限制)
message, err := websocket.FormatCloseMessage(code, reason)
if err != nil {
return err // 如 reason 超长或非 UTF-8,会返回错误
}
// 同步写入关闭消息帧(必须在 Close() 前调用)
if err := ws.WriteMessage(websocket.CloseMessage, message); err != nil {
return err
}
// 执行底层连接关闭(此时不会重复发送关闭帧)
return ws.Close()
}
// 使用示例
err := closeWithMessage(conn, websocket.CloseGoingAway, "Maintenance in progress")
if err != nil {
log.Printf("Failed to close connection gracefully: %v", err)
}✅ 关键要点说明:
- websocket.FormatCloseMessage 自动校验 reason 是否为合法 UTF-8 且长度 ≤123 字节,非法输入将返回错误;
- 必须先调用 WriteMessage(websocket.CloseMessage, ...),再调用 ws.Close() —— 后者仅清理资源,不重发关闭帧;
- 若跳过 WriteMessage 直接 Close(),浏览器收到的是无 reason 的默认关闭事件(event.reason === "", event.code === 1005);
- 常用状态码:websocket.CloseNormalClosure (1000)、websocket.CloseGoingAway (1001)、websocket.CloseInternalServerErr (1011)。
⚠️ 注意:golang.org/x/net/websocket 已于 2022 年正式归档,不再接受更新或安全修复。生产环境务必迁移至 Gorilla 或其他活跃维护的实现(如 nhooyr.io/websocket),以保障协议兼容性与安全性。

















