WebSocket绑定用户到房间需在Upgrade阶段解析参数(如room_id)并用sync.Map存储room_id→[]*websocket.Conn;广播时遍历目标房间连接列表,逐个WriteMessage并检查conn.IsClosed();断开时通过ReadMessage捕获io.EOF清理连接。

WebSocket连接时如何绑定用户到指定房间
Iris本身不内置房间管理,得靠自己维护映射关系。关键是在Upgrade阶段拿到连接后,立刻解析请求参数(比如URL query或header),提取room_id或user_id,再存进一个并发安全的结构里。
推荐用sync.Map存room_id → []*websocket.Conn,别用普通map——Go的map不是并发安全的,多个goroutine同时写会panic。
- 从
*http.Request里取参数:r.URL.Query().Get("room")或r.Header.Get("X-Room-ID") - 连接成功后,把
*websocket.Conn加进对应房间的切片,记得加锁或用sync.Map.LoadOrStore配合sync.Slice风格操作 - 务必在
defer里做清理:连接断开时,从对应房间切片中删掉该conn(注意遍历删除时别用for range直接删,要倒序或记录索引)
怎么给指定房间广播消息而不是全站推送
广播不能依赖Iris默认的ws.WriteMessage全局调用,必须手动遍历目标房间的连接列表。每次发消息前,先查sync.Map拿到该room_id对应的连接切片,再逐个WriteMessage。
注意:每个*websocket.Conn的WriteMessage是非阻塞但非并发安全的——同一连接不能被多个goroutine同时写。所以要么为每个conn配独立goroutine顺序写,要么用conn.SetWriteDeadline防卡死。
立即学习“go语言免费学习笔记(深入)”;
- 不要在HTTP handler里直接循环写:可能阻塞主线程,尤其房间人多时
- 建议封装一个
broadcastToRoom(roomID string, msg []byte)函数,内部用sync.Map.Range查房间,再启goroutine池控制并发度(比如最多5个goroutine并行写) - 写之前检查
conn.IsClosed(),避免向已断开连接写导致panic
客户端断开时如何及时清理房间成员
Iris的websocket.OnConnection只管建立,断开事件得靠OnDisconnect回调或主动轮询conn.ReadMessage返回io.EOF来捕获。后者更可靠——因为网络闪断、客户端强退都不会触发OnDisconnect。
典型做法是起一个goroutine专管读循环,一收到io.EOF或websocket.CloseMessage就执行清理逻辑。
- 在
OnConnection里立即启动读协程:go func() { for { _, _, err := conn.ReadMessage(); if err != nil { removeConnFromRoom(conn); return } } }() -
removeConnFromRoom里用sync.Map的Load拿到房间切片,再用atomic.Value或互斥锁保护切片修改 - 别忘了关掉conn:
conn.Close(),否则fd泄漏
为什么不用第三方库如gorilla/websocket而坚持用Iris原生WS
Iris的websocket包本质就是封装了gorilla/websocket,但隐藏了底层*websocket.Conn,导致你没法直接调用conn.Subprotocol()或自定义Upgrader.CheckOrigin。如果要做JWT校验、子协议协商、或精细控制握手头,就得切回原生gorilla,再用Iris的iris.WebSocket注册路由。
房间功能本身跟底层实现无关,但如果你发现iris websocket的OnDisconnect不触发、或WriteMessage偶发丢包,大概率是封装层吞了错误——这时候直接换gorilla更省心。
- 切换方法:用
app.Get("/ws", func(ctx iris.Context) { upgrader.Upgrade(ctx.ResponseWriter(), ctx.Request(), nil) }),然后自己管conn生命周期 - 房间管理代码完全复用,只是conn类型从
iris/ws.Conn变成*websocket.Conn - 代价是失去Iris的context集成(比如无法直接用
ctx.Values().Get),需提前把必要数据塞进closure


















