0

0

Go并发编程中recover是否安全_Go异常恢复机制说明

P粉602998670

P粉602998670

发布时间:2026-01-19 03:51:23

|

665人浏览过

|

来源于php中文网

原创

recover仅在同goroutine的defer中调用才有效,用于捕获panic;跨goroutine无效,且恢复后状态可能损坏,应优先预防而非依赖recover。

go并发编程中recover是否安全_go异常恢复机制说明

recover 只在 panic 发生时有效,且必须在 defer 中调用

recover 不是通用的错误捕获机制,它只对当前 goroutine 中由 panic 触发的异常起作用。如果没在 defer 函数里调用,recover 会直接返回 nil,什么也捞不到。

常见错误是把 recover 放在普通函数里、或者放在 defer 外面:

func badExample() {
    recover() // 永远返回 nil,毫无意义
    defer func() {
        // 这里才对,但得确保 panic 确实发生在 defer 执行前
        if r := recover(); r != nil {
            log.Println("caught:", r)
        }
    }()
    panic("boom")
}
  • recover 必须紧挨着 defer,且该 defer 必须在 panic 之前注册(即在同 goroutine 中先执行 defer 注册,再触发 panic
  • 跨 goroutine 的 panic 无法被其他 goroutine 的 recover 捕获 —— Go 不支持“全局异常处理器
  • 如果 panic 后程序已退出当前函数(比如 panic 在 goroutine 起始处就发生),而 defer 还没来得及运行,recover 就失效了

goroutine 崩溃时 recover 无法阻止程序终止

主 goroutine(main)中未被 recoverpanic 会导致整个程序退出;其他 goroutine 中未 recover 的 panic 虽不会终止进程,但该 goroutine 会静默死亡,且不会通知其他协程。

这意味着:你不能靠一个全局 recover 来“兜底”所有 goroutine 的错误。

  • 每个可能 panic 的 goroutine 都得自己配 defer + recover
  • 别指望在 main 函数里 defer 一次就能 catch 子 goroutine 的 panic
  • 子 goroutine panic 后若没 recover,日志都不打 —— 默认行为是 silent exit,容易误判为“逻辑没执行到”

recover 后继续运行是安全的,但状态可能已损坏

recover 能让 goroutine 从 panic 栈展开中恢复执行,控制权回到 defer 函数之后的代码,这点是安全的。但不等于“一切如常”。

花生AI
花生AI

B站推出的AI视频创作工具

下载

关键问题是:panic 可能发生在任意语句中间,比如刚写了一半结构体字段、刚 unlock 了 mutex、刚 close 了 channel……此时程序状态大概率不一致。

  • 不要在 recover 后继续使用可能被中断修改的共享变量(如全局 map、未加锁的计数器)
  • 避免在 recover 后重试原操作 —— 很可能重复提交、重复消费、重复写库
  • 推荐做法:recover 后只做清理(close channel、unlock、log)、然后 return 或启动新 goroutine 隔离后续逻辑

替代方案比盲目 recover 更可靠

很多场景下,与其依赖 recover,不如提前预防 panic。Go 的并发模型鼓励显式错误处理,而非异常兜底。

  • sync.Pool 替代频繁 new + panic 风险的切片扩容
  • context.Context 控制超时和取消,而不是靠 panic 中断流程
  • 对不可信输入(如 JSON 解析、类型断言)优先用 ok-idiom:v, ok := x.(T),而非直接断言后 panic
  • 第三方库调用前查文档:是否明确说明会 panic?比如 json.Unmarshal(nil, &v) 会 panic,应提前判空

真正需要 recover 的地方其实很少:主要是插件系统、HTTP handler 顶层兜底、或封装 Cgo 调用时防止崩溃穿透。其它时候,它更像一把双刃剑 —— 用错比不用还危险。

相关文章

编程速学教程(入门课程)
编程速学教程(入门课程)

编程怎么学习?编程怎么入门?编程在哪学?编程怎么学才快?不用担心,这里为大家提供了编程速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

412

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

533

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

310

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

74

2025.09.10

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

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

196

2025.06.09

golang结构体方法
golang结构体方法

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

189

2025.07.04

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

391

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

72

2026.01.16

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.3万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.2万人学习

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

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