0

0

如何在Golang中处理WebSocket的Close Error Go语言连接关闭代码解析

P粉602998670

P粉602998670

发布时间:2026-03-12 09:58:32

|

985人浏览过

|

来源于php中文网

原创

websocket连接异常关闭时返回closeabnormalclosure,是tcp断连的协议层兜底;主动调用writemessage发关闭帧才得closenormalclosure;读出错后须立即检查iscloseerror并安全处理,不可defer close或继续读写。

如何在golang中处理websocket的close error go语言连接关闭代码解析

WebSocket连接关闭时为什么总收到websocket.CloseAbnormalClosure

Go 的 gorilla/websocket 包里,只要底层 TCP 连接断了(比如客户端直接关浏览器、网络中断、Nginx 代理超时),服务端读消息时几乎必然触发 websocket.CloseAbnormalClosure —— 它不是你代码写错了,而是协议层的“默认兜底”。真正由你主动调用 conn.WriteMessage(websocket.CloseMessage, ...) 关闭的,才会返回 websocket.CloseNormalClosure

常见错误现象:read: connection closeduse of closed network connection 跟着一个 websocket.CloseAbnormalClosure 一起出现,说明读操作已经失败,再试图 WriteMessage 就会 panic。

  • 必须在 err != nil 后立刻检查 websocket.IsCloseError(err, ...),而不是直接 return 或继续写
  • 不要在 defer conn.Close() 里指望它能“安全收尾”:如果连接已断,Close() 本身可能 panic
  • 若需发关闭帧,必须在读出错前、且连接还可用时调用 conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(...))

如何正确响应客户端发来的CloseMessage

客户端主动关闭时,会先发一个 CloseMessage 帧,服务端要读到它,再回一个同类型的帧,才算标准握手。但 conn.ReadMessage() 不会把 CloseMessage 当成普通消息返回,而是直接返回 err 并设为 websocket.CloseMessage 类型的错误。

  • websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) 判断是否为合法关闭请求
  • 判断成立后,立即调用 conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
  • 写完就 return,别再读或写其他消息,否则可能触发 use of closed network connection
  • 注意:FormatCloseMessage 第二个参数是原因字符串,长度不能超过 123 字节,超长会被截断或报错

conn.SetReadDeadlineconn.SetWriteDeadline 怎么配

WebSocket 连接长期空闲时,中间设备(如负载均衡、防火墙)常会静默断连。靠心跳保活是必须的,而 deadline 是心跳机制的基础设施。但读写 deadline 必须分开设,且不能只设一个。

ColorMagic
ColorMagic

AI调色板生成工具

下载

立即学习go语言免费学习笔记(深入)”;

  • 读 deadline 应略大于心跳间隔(例如心跳 30s,读 deadline 设 35s),否则心跳包还没来就读超时,误判为断连
  • 写 deadline 要比单次写操作预期耗时稍长(比如发一条消息通常
  • 每次成功 ReadMessageWriteMessage 后,都得重置对应方向的 deadline,否则过期后下一次操作直接报 i/o timeout
  • 不要在 for 循环外一次性设置 deadline:它是一次性的,超时后需手动重置

为什么defer conn.Close()goroutine 里容易失效

典型写法是起一个 goroutine 处理读,另一个处理写。如果读 goroutine 因错误退出,defer conn.Close() 只在该 goroutine 结束时触发,但写 goroutine 可能还在跑,继续往已关闭的连接写数据,就会 panic。

  • 不要依赖单个 goroutine 的 defer 关闭连接,改用显式状态控制(如 sync.Once + close(doneCh)
  • 所有读写操作前,先 select 检查 doneCh 是否已关闭,避免竞态
  • conn.Close() 本身不是并发安全的,多个 goroutine 同时调用会 panic;确保全局只有一次调用机会
  • 关闭连接后,记得关闭关联的 channel(如消息发送 channel)、取消 context,防止 goroutine 泄漏

最麻烦的点其实是:关闭帧的发送时机和错误类型的交叉判断——IsCloseError 返回 true 时,连接未必还能写;而 IsUnexpectedCloseError 为 true 时,往往已经来不及发任何帧了。这点不细看文档很容易漏掉。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

210

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

247

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

356

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

214

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

409

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

490

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

201

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

1438

2025.06.17

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 6.1万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号