前言
在学习 Go 的 websocket,发现 gorilla/websocket 已经停止维护了。
在 Go Packages 上找到了另外一个推荐使用的 websocket 库 nhooyr.io/websocket 。
Github 仓库: github.com/nhooyr/webs…
websocket
websocket 是用于 Go 的极小惯用 WebSocket 库。
安装
go get nhooyr.io/websocket
亮点
- 极小和惯用的API
- 支持上下文 context.Context
- 完整通过 WebSocket 的测试autobahn-testsuite
- 单依赖
- 在 wsjson 和 wspb 子包中提供 JSON 和 protobuf 的辅助处理
- 零分配读写
- 并发写入
- 关闭握手
- net.Conn 包装
- Ping pong API
- RFC 7692 消息别压缩
- 编译为 Wasm
路线图
- HTTP/2 #4
示例
这是一个产品级品质的示例,展示了完整的API,查看 echo 示例。
这是一个全栈示例,查看 聊天示例。
服务端
http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
c, err := websocket.Accept(w, r, nil)
if err != nil {
// ...
}
defer c.Close(websocket.StatusInternalError, "the sky is falling")
ctx, cancel := context.WithTimeout(r.Context(), time.Second*10)
defer cancel()
var v interface{}
err = wsjson.Read(ctx, c, &v)
if err != nil {
// ...
}
log.Printf("received: %v", v)
c.Close(websocket.StatusNormalClosure, "")
})
客户端
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
c, _, err := websocket.Dial(ctx, "ws://localhost:8080", nil)
if err != nil {
// ...
}
defer c.Close(websocket.StatusInternalError, "the sky is falling")
err = wsjson.Write(ctx, c, "hi")
if err != nil {
// ...
}
c.Close(websocket.StatusNormalClosure, "")
比较
gorilla/websocket(已停止维护)
gorilla/websocket 的优点:
nhooyr.io/websocket 的优点:
-
极小,惯用的API
- nhooyr.io/websocket 和 gorilla/websocket 对应比较的 go 文档
-
net.Conn 包装
-
零分配读写 (gorilla/websocket#535)
-
完整支持上下文 context.Context
-
Dial 使用 net/http.Client
- 将来会支持简单支持 HTTP/2
- Gorilla 直接写入到 net.Conn ,然后会复制 net/http.Client 的特性
-
并发写入
-
关闭握手 (gorilla/websocket#448)
-
惯用的 ping pong API
- Gorilla 需要在发送 Ping 之前注册 pong 回调
-
可编译为 Wasm (gorilla/websocket#432)
-
1.75x 在纯 Go 中实现的更快的 WebSocket 屏蔽。
- Gorilla 的实现相对慢,并使用了 unsafe。
-
完整的 消息别压缩 扩展支持
- Gorilla 只支持非上下文接管模式
- 我们使用 klauspost/compress 减少内存占用 (gorilla/websocket#203)
-
关闭读 的辅助处理 (gorilla/websocket#492)
-
实时维护 (gorilla/websocket#370)
golang.org/x/net/websocket
golang.org/x/net/webso… 也已不推荐使用 了。查看 golang/go/issues/18152 。
net.Conn 有助于传送给 nhooyr.io/websocket 。
gobwas/ws
gobwas/ws 拥有极其灵活的API,这样它可以用于事件驱动风格以提高性能。查看作者的 博客投稿.
无论如何,编写惯用的 Go , nhooyr.io/websocket 会更快且更简便。