用 fiber 启动 websocket 服务端直接调用 app.get + websocket.new 即可,无需中间件;路径须显式匹配,handler 签名必须为 func(*websocket.conn),需 defer c.close();readmessage/writemessage 阻塞且断连立即返错,须检查 err 并及时 return;协程中须 select 监听 c.context().done() 避免泄露。

如何用 Fiber 启动 WebSocket 服务端
直接调用 app.Get + websocket.New 即可,不需要额外中间件或路由适配器。Fiber v2/v3 都内置了 websocket 包支持,但注意 v3 的导入路径是 github.com/gofiber/fiber/v3/websocket,v2 是 github.com/gofiber/websocket/v2。
关键点在于:路径必须显式匹配,且 handler 函数签名要接收 *websocket.Conn(不是 fiber.Ctx);websocket.New 会自动处理升级头、校验和连接封装。
- 错误写法:
app.Get("/ws", func(c fiber.Ctx) error { ... })—— 这里没走 WebSocket 升级流程,会返回 400 或直接 panic - 正确写法:
app.Get("/ws", websocket.New(func(c *websocket.Conn) { ... })) - 别漏掉
defer c.Close(),否则连接不释放,fd 耗尽后新连接会被拒
conn.ReadMessage 和 conn.WriteMessage 怎么安全收发
这两个函数都是阻塞的,且在连接断开时会立即返回错误(如 websocket.ErrCloseSent、io.EOF、net.OpError),不能靠超时或重试兜底——必须主动检查错误并退出 goroutine。
常见错误是把读写逻辑包在无限 for 循环里却不判断 err:
for {<br> _, msg, err := c.ReadMessage()<br> if err != nil {<br> // ❌ 没处理就 continue,会反复 panic 或卡死<br> continue<br> }<br> c.WriteMessage(websocket.TextMessage, msg)<br>}
正确做法是遇到任何非 nil 错误立刻 return:
-
if err != nil && !websocket.IsUnexpectedCloseError(err) && !errors.Is(err, io.EOF)→ 可以忽略(比如正常关闭) - 其他 err(包括
websocket.IsCloseError(err, websocket.CloseAbnormalClosure))→ 立即return - 写操作失败也一样:只要
c.WriteMessage(...)返回 err,就该停止发送并退出
如何避免协程泄露:必须传入并监听 ctx.Done()
Fiber 的 websocket.Conn 不自带 context 绑定,但 HTTP 连接断开时,底层 fasthttp 会 cancel 关联的 context.Context。如果你在 handler 里另起 goroutine 处理消息广播或心跳,不传 context 就无法感知连接已死。
典型泄露场景:
- 在
websocket.New的 handler 里启动一个长期运行的 goroutine,只监听broadcastChan,却没监听c.Context().Done() - 把
c存进全局 map,后续用另一个 goroutine 定期往里写,但没检查连接是否还活着
解决方法很直接:在 goroutine 内部用 select 优先响应 c.Context().Done():
go func() {<br> for {<br> select {<br> case return // 连接已断,退出<br> case msg := if err := c.WriteMessage(websocket.TextMessage, msg); err != nil {<br> return // 写失败,也退出<br> }<br> }<br> }<br>}()
Fiber WebSocket 客户端能复用 HTTP 连接吗
不能。Fiber 的 websocket 包只提供服务端能力,没有客户端实现。所谓“HTTP 客户端转 WebSocket”是误解——WebSocket 协议必须从 HTTP 升级(Upgrade: websocket)开始,客户端需用标准 gorilla/websocket 或 nhooyr.io/websocket 连接,和服务端 Fiber 无关。
如果你在 Fiber 服务里需要主动连别的 WebSocket 服务(比如推送网关),得单独用第三方 client 库,和 Fiber 的 HTTP client(fiber.App.Test 或 fasthttp.Do)完全不兼容。
容易被忽略的一点:Fiber 的 Context 生命周期只到 handler 返回为止,千万别把 c.Context() 保存下来传给后台 goroutine —— 连接一断,这个 context 就被 cancel,但 goroutine 可能还在空转。











