0

0

如何使用Golang recover捕获panic_Golang异常恢复机制解析

P粉602998670

P粉602998670

发布时间:2026-01-14 15:13:10

|

228人浏览过

|

来源于php中文网

原创

recover必须在defer中调用才有效,仅在panic发生且当前goroutine的defer链执行时返回panic值,否则返回nil;它不回滚副作用,仅实现goroutine软着陆。

如何使用golang recover捕获panic_golang异常恢复机制解析

recover 必须在 defer 中调用才有效

直接在普通函数体里写 recover() 永远返回 nil,它只在 panic 正在发生、且当前 goroutine 的 defer 链正在执行时才有意义。Go 运行时会把 panic 的值“传递”给正在执行的 defer 函数中的 recover() 调用。

  • 必须搭配 defer 使用,典型模式是:
    defer func() {
        if r := recover(); r != nil {
            // 处理 panic 值
            log.Printf("panic recovered: %v", r)
        }
    }()
  • 如果 defer 是匿名函数,且该函数内没调用 recover(),或者调用位置不在 panic 触发之后(比如提前 return),就捕获不到
  • recover 不是“全局开关”,它只对**当前 goroutine** 有效;其他 goroutine 的 panic 不会影响它,也不能被它捕获

recover 返回值类型是 interface{},需手动断言

recover() 返回的是任意类型的 panic 值,不是错误对象。如果你用 panic("oops"),recover 得到的是 string;如果用 panic(errors.New("db fail")),得到的是 *errors.errorString;甚至可能是自定义结构体。

  • 不要假设返回值一定是 error 类型,直接转成 error 可能 panic:
    if err := recover().(error); err != nil { ... } // 危险!类型断言失败会再 panic
  • 安全做法是先做类型检查:
    r := recover()
    switch x := r.(type) {
    case string:
        log.Printf("panic string: %s", x)
    case error:
        log.Printf("panic error: %v", x)
    default:
        log.Printf("panic unknown type: %T, value: %v", x, x)
    }
  • 注意:nil 本身不能被 recover 捕获 —— panic(nil) 会导致程序直接崩溃,recover() 无法拦截

recover 无法恢复已释放的资源或已提交的状态

recover 只是让 goroutine 从 panic 状态中“软着陆”,继续执行 defer 后的代码,但它不撤销任何已发生的副作用。

  • 文件已写入、数据库事务已提交、HTTP 响应头已发送……这些都不会回滚
  • recover 后继续执行的逻辑,仍要面对一个可能处于不一致状态的对象(比如 struct 字段部分初始化失败)
  • 常见误用:在 HTTP handler 里 recover 后直接返回 200 OK,但其实业务逻辑已经中断,响应内容为空或错乱
  • 正确思路是:recover → 记录上下文(如 request ID、panic )→ 返回 500 或降级响应 → 避免暴露内部细节

嵌套 defer 和多层 recover 的行为容易误判

一个函数里可以有多个 defer,它们按后进先出(LIFO)顺序执行;每个 defer 里的 recover() 都有机会捕获 panic,但只有第一个成功调用的能拿到 panic 值,后续都返回 nil

来福FM
来福FM

来福 - 你的私人AI电台

下载

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

  • 下面这段代码只会打印一次 "recovered":
    func f() {
        defer func() {
            if r := recover(); r != nil {
                log.Println("recovered")
            }
        }()
        defer func() {
            if r := recover(); r != nil {
                log.Println("also recovered?") // 永远不会执行
            }
        }()
        panic("boom")
    }
  • 跨函数调用时,recover 只作用于当前函数的 defer 链;父函数即使有 defer + recover,也捕获不到子函数里已被子函数自身 recover 掉的 panic
  • 在中间件或 wrapper 函数中统一 recover 是可行的,但要注意别和业务层的 recover 冲突 —— 建议只在最外层(如 HTTP handler、goroutine 入口)做一次 recover

recover 不是 try/catch,它没有“异常传播”概念,也没有 finally 语义。真正难的从来不是写那行 recover(),而是判断哪里该用、哪里不该用,以及 panic 之后你还敢信任哪些数据。

相关专题

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

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

178

2024.02.23

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

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

226

2024.02.23

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

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

337

2024.02.23

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

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

208

2024.03.05

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

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

388

2024.05.21

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

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

195

2025.06.09

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

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

190

2025.06.10

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

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

192

2025.06.17

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

12

2026.01.14

热门下载

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

精品课程

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

共32课时 | 3.7万人学习

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

共10课时 | 0.8万人学习

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

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