跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Go语言如何实现WebSocket通信_WebSocket基础用法

Go标准库不支持WebSocket,需用gorilla/websocket;服务端用Upgrader升级连接后读写消息,客户端需手动拨号并处理重连与超时。 Go标准库不支持WebSocket,必须用第三方包 Go语言原生
net/http
包只提供HTTP协议支持,没有内置WebSocket实现。直接调用
http.ResponseWriter
的
Write
方法或试图升级连接会失败,因为缺少WebSocket握手、帧解析和心跳等关键逻辑。 主流选择是
gorilla/websocket
——它稳定、文档清晰、被大量生产项目验证。别用已归档的
golang.org/x/net/websocket
,也不建议从零手写WebSocket帧处理。 服务端:用
gorilla/websocket
建立连接并读写消息 核心是
websocket.Upgrader
升级HTTP请求,再用
*websocket.Conn
收发数据。注意升级过程必须在HTTP handler中完成,且不能有任何前置
Write
或
Header
修改(否则触发
http: multiple response.WriteHeader calls
错误)。
Upgrader.CheckOrigin
默认拒绝 跨域 请求,开发时可临时设为
func(r *http.Request) bool { return true }
,生产环境应校验
Origin
头 读取消息用
conn.ReadMessage()
,返回
(int, []byte, error)
,第一个值是消息类型(
websocket.TextMessage
或
websocket.BinaryMessage
) 发送消息用
conn.WriteMessage()
,第二个参数必须是
[]byte
;若传字符串,需先转
[]byte("hello")
连接应显式关闭:
conn.Close()
,否则可能泄漏goroutine和文件描述符
package main import ( "log" "net/http" "github.com/gorilla/websocket" ) var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } func wsHandler(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Println("Upgrade error:", err) return } defer conn.Close() for { _, msg, err := conn.ReadMessage() if err != nil { log.Println("Read error:", err) break } if err := conn.WriteMessage(websocket.TextMessage, msg); err != nil { log.Println("Write error:", err) break } } } func main() { http.HandleFunc("/ws", wsHandler) log.Fatal(http.ListenAndServe(":8080", nil)) }
客户端:用
websocket.Dial
连接并处理断线重连 浏览器 端用
new WebSocket("ws://localhost:8080/ws")
即可,但Go客户端需主动拨号。常见陷阱是忽略TLS配置(
wss://
需传
&tls.Config{InsecureSkipVerify: true}
仅限测试)、未设置读写超时导致goroutine卡死。 立即学习 “ go语言免费学习笔记(深入) ”;
websocket.DefaultDialer
默认无超时,务必设置
TLSClientConfig
和
Proxy
(如需代理) 读写操作可能阻塞,建议用
conn.SetReadDeadline()
和
conn.SetWriteDeadline()
控制超时 断线后不能复用旧
*websocket.Conn
,必须重新
Dial
;重连逻辑需自己实现(例如指数退避) 发送JSON数据时,先
json.Marshal
再
WriteMessage
;接收时先
ReadMessage
再
json.Unmarshal
消息粘包与并发安全:每个连接应独占一个goroutine
websocket.Conn
本身不是并发安全的——多个goroutine同时调用
WriteMessage
会panic(
concurrent write to websocket connection
)。但
ReadMessage
可以并发调用,只要写操作被串行化。 典型模式:一个goroutine循环
ReadMessage
,另一个goroutine负责
WriteMessage
,通过
chan []byte
通信 不要在HTTP handler里直接处理业务逻辑,应把
conn
交给worker goroutine,并用
defer conn.Close()
确保清理 大消息(>1MB)可能触发
websocket: close sent
,需调大
Upgrader.ReadBufferSize
和
WriteBufferSize
真正难的是状态同步和连接生命周期管理,比如用户登录态如何绑定到Conn、如何广播消息给房间内所有人——这些不在WebSocket协议层,得自己设计。

相关文章