如何在Golang中实现WebSocket广播_使用Channel和协程分发消息
技术百科
P粉602998670
发布时间:2026-01-01
浏览: 次 Golang WebSocket广播核心是channel消息中枢与goroutine并发分发,需确保读写分离、连接安全、异常清理;用sync.RWMutex保护clients map,设WriteDeadline防慢连接,recover捕获写错并清理连接。
在Golang中实现WebSocket广播,核心是用channel做消息中枢、用goroutine做并发分发,避免阻塞主线程。关键不在“写多少代码”,而在于读写分离、连接安全、异常清理这三点是否到位。
定义广播通道与客户端集合
声明一个全局的broadcast channel,类型为chan []byte或自定义消息结构体,所有客户端发来的消息都先投递到这里。同时维护一个并发安全的客户端集合:
- 用
map[*websocket.Conn]bool记
录活跃连接 - 用
sync.RWMutex保护读写,注册/注销时加写锁,广播遍历时加读锁 - 避免直接用
sync.Mutex——读多写少场景下RWMutex能显著提升吞吐
启动独立广播协程
服务启动时就go handleBroadcast(),让它持续监听broadcast channel:
- 收到消息后,先加读锁遍历clients map
- 对每个连接调用
conn.WriteMessage(websocket.TextMessage, msg) - 务必设置
conn.SetWriteDeadline(time.Now().Add(5 * time.Second)),防止慢连接拖垮整个广播 - 写失败时recover捕获panic,关闭该conn并从map中移除
每个连接配两个协程:读+写分离
新连接升级成功后,立即启动两个goroutine:
-
读协程:循环
conn.ReadMessage(),把原始消息(或解析后的结构体)推入broadcastchannel -
写协程:可选——如果需要向特定用户单播或做消息过滤,可为每个client分配独立
send chan []byte,由该协程消费并写出 - 读出错或连接关闭时,触发注销流程:向
unregisterchannel发信号,或直接加锁删除map条目
前端连接与消息收发很简单
浏览器端只需几行JavaScript:
const ws = new WebSocket("ws://localhost:8000/ws")ws.onmessage = e => console.log("收到:", e.data)-
ws.send("你好")即可触发后端广播 - 建议加
onerror和onclose处理断连重试逻辑
基本上就这些。不复杂但容易忽略write deadline、panic恢复和map清理——这三个点没做好,上线后扛不住几十个并发就会卡死或内存暴涨。
# 后端
# 浏览器
# go
# golang
# javascript
# java
# 前端
# websocket
# 浏览器端
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 如何在Golang中使用闭包_封装变量与函数作用域
- Win11怎样安装企业微信_Win11安装企业微信
- Win11时间不对怎么同步_Win11自动校准互联
- C++如何使用std::optional?(处理可
- Win11此电脑不在桌面上_Windows 11桌
- php订单日志怎么按金额排序_php按订单金额排序
- Win11如何更改用户账户文件夹名称 Win11修
- Windows11怎样开启游戏模式_Windows
- WindowsUSB驱动安装异常怎么办_USB驱动
- 如何用正则与预处理高效拦截带干扰符的恶意域名
- How to Properly Use NumPy
- Win11如何设置系统声音_Win11系统声音调整
- c++的static关键字有什么用 静态变量和静态
- PHP cURL GET请求:正确设置请求头与身份
- Win10电脑怎么设置网络名称_Windows10
- php与c语言在嵌入式中有何区别_对比两者在硬件控
- Win10任务栏天气和资讯怎么关闭 Win10禁用
- 如何在Golang中验证模块完整性_Golangg
- Windows家庭版如何开启组策略(gpedit.
- Windows如何拦截2345弹窗广告_Windo
- c++的STL算法库find怎么用 在容器中查找指
- 如何在Golang中捕获JSON序列化错误_Gol
- Python项目回滚策略_发布安全说明【指导】
- PHP主流架构怎么处理表单验证_规则与自定义【技巧
- 如何减少Golang内存碎片化_Golang内存分
- Win11怎样安装搜狗输入法_Win11安装搜狗输
- c++ std::future和std::prom
- 如何使用Golang开发简单的聊天室消息存储_Go
- Python异步编程高级项目教程_asyncio协
- 如何在Golang中处理二进制数据_Golang
- Windows服务无法启动错误1067是什么_进程
- Python异步网络编程_aiohttp说明【指导
- 如何使用Golang捕获并记录协程panic_保证
- Win11截图快捷键是什么_Win11自带截图工具
- c++中如何使用auto关键字_c++11类型推导
- Windows服务持续崩溃怎样修复_系统服务保护机
- mac怎么看硬盘大小_MAC查看磁盘存储空间与文件
- Python函数参数高级用法_默认值与可变参数解析
- Python对象比较与排序_魔术方法解析【教程】
- Windows10系统服务优化指南_Win10禁用
- Mac自带的词典App怎么用_Mac添加和使用多语
- mac怎么安装字体_MAC添加第三方字体与字体册管
- 如何使用Golang匿名函数_快速定义临时函数逻辑
- 如何使用Golang recover捕获panic
- PHP主流架构怎么监控运行状态_工具推荐【操作】
- Win11怎么关闭小组件_Win11禁用任务栏天气
- Win11更新后变慢怎么办_Win11系统更新后卡
- Win11声音太小怎么办_Windows 11开启
- Win11时间怎么同步到原子钟 Win11高精度时
- Win11输入法选字框不见了怎么办_Win11输入

录活跃连接
QQ客服