Golang中如何使用defer和recover来捕获goroutine中的panic

golang中如何使用defer和recover来捕获goroutine中的panic

defer和recover是Golang中处理panic的利器。它们允许你在程序发生崩溃时进行清理工作,并有机会恢复程序的运行。简单来说,defer用于延迟执行函数调用,而recover则用于捕获panic。

解决方案

在Golang中,defer和recover通常一起使用,以优雅地处理goroutine中的panic。

defer语句:

defer

关键字用于注册一个函数调用,这个函数会在包含它的函数执行完毕(正常返回或发生panic)之后执行。 这保证了资源清理等操作总能被执行。 可以理解为一种延迟执行的机制,类似于其他语言中的

finally

块,但更加灵活。

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

recover函数:

recover

是一个内建函数,它用于重新获得 panic 控制权。 当一个函数调用

panic

时,正常的执行流程会被中断,并沿着调用栈向上寻找

defer

语句。 如果

defer

语句中调用了

recover

,那么

panic

会被捕获,程序会从

recover

调用的地方继续执行,

recover

函数会返回

panic

的值。 如果没有

recover

被调用,

panic

会继续向上层传递,最终导致程序崩溃。

一个典型的使用场景如下:

package mainimport (    "fmt"    "runtime")func main() {    go func() {        defer func() {            if r := recover(); r != nil {                fmt.Println("Recovered from panic:", r)                // 打印堆栈信息,方便调试                buf := make([]byte, 2048)                runtime.Stack(buf, false)                fmt.Printf("Stack trace:n%sn", buf)            }        }()        // 模拟一个panic        panic("Something went wrong!")    }()    // 避免程序立即退出,让goroutine有时间执行    select {}}

在这个例子中,我们在goroutine中使用

defer

语句注册了一个匿名函数。这个匿名函数会调用

recover

来捕获panic。如果goroutine中发生了panic,

recover

会捕获它,并打印出panic的信息和堆栈信息。程序会继续执行,而不是崩溃。 注意,

recover

必须在

defer

函数中调用才有效。

为什么需要打印堆栈信息? 仅仅捕获panic是不够的,还需要了解panic发生的原因。 堆栈信息可以帮助你定位到panic发生的具体位置,从而更好地解决问题。

副标题1:如何避免过度使用defer导致性能问题?

defer

虽然强大,但过度使用也会带来性能问题。每次调用

defer

都会增加函数调用的开销。 特别是在循环中,频繁使用

defer

会显著降低性能。

避免过度使用

defer

的方法:

只在必要时使用defer: 只在需要确保资源清理等操作必须执行的情况下使用

defer

。 例如,关闭文件、释放锁等。避免在循环中使用defer: 如果需要在循环中执行清理操作,尽量手动执行,而不是使用

defer

。考虑使用资源池: 对于需要频繁创建和销毁的资源,可以使用资源池来减少

defer

的使用。

例如,下面是一个错误的使用

defer

的例子:

func processData(data []int) {    for _, value := range data {        f, err := os.Open("data.txt") // 假设打开文件会panic        if err != nil {            panic(err)        }        defer f.Close() // 每次循环都defer一个close,效率很低        // ... 处理文件内容    }}

更好的做法是:

func processData(data []int) {    f, err := os.Open("data.txt")    if err != nil {        panic(err)    }    defer f.Close() // 只defer一次    for _, value := range data {        // ... 处理文件内容    }}

副标题2: recover() 返回 nil 的情况有哪些?

recover()

函数只有在

defer

函数中被调用,并且当前 goroutine 发生了

panic

时才会返回

panic

的值。 在其他情况下,

recover()

会返回

nil

。

具体来说,以下情况

recover()

会返回

nil

:

没有发生panic: 如果当前 goroutine 没有发生

panic

,

recover()

会返回

nil

。recover() 不在 defer 函数中调用:

recover()

必须在

defer

函数中调用才有效。如果在

defer

函数之外调用,

recover()

会返回

nil

。defer 函数没有被执行: 如果包含

recover()

的

defer

函数没有被执行(例如,函数提前返回),

recover()

也会返回

nil

。panic 被其他 recover() 捕获: 如果

panic

已经被其他

recover()

函数捕获,那么后续的

recover()

函数也会返回

nil

。

因此,在使用

recover()

时,一定要注意检查返回值是否为

nil

,以避免出现意外情况。

副标题3:如何优雅地处理panic并重启goroutine?

有时候,我们希望在goroutine发生panic后,不仅要捕获panic,还要重启goroutine,以保证程序的稳定性。 一种常见的做法是使用一个循环来不断地启动goroutine,并在goroutine内部使用defer和recover来捕获panic。

package mainimport (    "fmt"    "time")func worker() {    defer func() {        if r := recover(); r != nil {            fmt.Println("Worker panicked:", r)            // 重新启动worker goroutine            go worker()        }    }()    // 模拟worker goroutine的工作    for i := 0; i < 5; i++ {        fmt.Println("Worker doing work:", i)        time.Sleep(time.Second)        if i == 2 {            panic("Worker encountered an error!")        }    }}func main() {    // 启动worker goroutine    go worker()    // 避免程序立即退出    select {}}

在这个例子中,

worker

函数使用

defer

和

recover

来捕获

panic

。 如果

worker

函数发生了

panic

,

recover

会捕获它,并重新启动一个新的

worker

goroutine。 这样可以保证即使

worker

goroutine 发生

panic

,程序也能继续运行。

这种重启机制的潜在问题: 如果panic是由于代码中的bug引起的,那么不断重启goroutine可能会导致程序陷入死循环。 因此,在重新启动goroutine之前,应该仔细分析panic的原因,并尝试修复bug。 此外,还可以添加一些限制,例如,限制goroutine重启的次数,以避免程序陷入死循环。

副标题4:defer 语句的执行顺序是什么?

在一个函数中,可以有多个

defer

语句。 这些

defer

语句会按照它们声明的逆序执行。 也就是说,最后一个声明的

defer

语句会最先执行,第一个声明的

defer

语句会最后执行。

例如:

package mainimport "fmt"func main() {    defer fmt.Println("First defer")    defer fmt.Println("Second defer")    defer fmt.Println("Third defer")    fmt.Println("Main function")}

输出结果:

Main functionThird deferSecond deferFirst defer

理解

defer

语句的执行顺序对于编写正确的代码非常重要。 例如,在需要释放多个资源时,应该按照资源分配的逆序来释放它们,以避免出现资源泄漏等问题。

副标题5:panic 和 os.Exit 的区别?

panic

和

os.Exit

都可以用于终止程序的执行,但它们之间存在一些重要的区别。

panic:

panic

会导致程序中断正常的执行流程,并沿着调用栈向上寻找

defer

语句。

defer

语句会被执行,然后

panic

会继续向上层传递,直到被

recover

捕获,或者程序崩溃。

panic

通常用于处理不可恢复的错误,例如,程序内部的逻辑错误、数据损坏等。os.Exit:

os.Exit

会立即终止程序的执行,不会执行任何

defer

语句。

os.Exit

通常用于处理外部错误,例如,命令行参数错误、文件不存在等。

选择使用

panic

还是

os.Exit

取决于具体的场景。 如果希望在程序退出前执行一些清理操作,应该使用

panic

。 如果希望立即终止程序的执行,并且不需要执行任何清理操作,可以使用

os.Exit

。

总结

defer

和

recover

是 Golang 中处理

panic

的重要工具。 合理地使用它们可以提高程序的健壮性和可靠性。 但也要注意避免过度使用

defer

导致性能问题,并理解

recover()

返回

nil

的情况。 在处理

panic

时,不仅要捕获它,还要了解

panic

发生的原因,并采取相应的措施,例如,重新启动 goroutine 或修复 bug。

以上就是Golang中如何使用defer和recover来捕获goroutine中的panic的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1402954.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Golang Windows与WSL环境协同开发方法
上一篇 2025年12月15日 19:09:19
垃圾回收器如何识别栈中的对象引用?
下一篇 2025年12月15日 19:09:35

相关推荐

  • TCL雷鸟创新X3 Pro入选《时代》2025最佳发明

    近日,美国《时代》杂志(time)发布了万众期待的2025年度最佳发明榜单,tcl雷鸟创新与苹果、华为、比亚迪、deepseek等全球知名科技企业共同登榜,其创新成果获得国际高度认可。 在本次榜单中,中国科技力量表现抢眼:华为Pura80 Ultra引领高端智能手机潮流,比亚迪持续领跑新能源汽车赛道…

    2026年10月1日
    200
  • 使用Sublime配合Sass开发|前端样式管理更加轻松灵活

    使用Sublime配合Sass开发|前端样式管理更加轻松灵活使用Sublime配合Sass开发|前端样式管理更加轻松灵活使用Sublime配合Sass开发|前端样式管理更加轻松灵活使用Sublime配合Sass开发|前端样式管理更加轻松灵活

    使用 sublime 搭配 sass 开发可提升 css 编写效率。1. 安装 sass 插件如 sassbuild 或 scss builder,通过 package control 安装并配置项目路径;2. 使用变量、嵌套、混合等特性简化样式编写,实现高效维护;3. 按模块划分 scss 文件并…

    2026年10月1日 • 用户投稿
    1200
  • 买BlackBerry手机怎么挑安全—BlackBerry手机安全如何选择方法

    买BlackBerry手机怎么挑安全—BlackBerry手机安全如何选择方法买BlackBerry手机怎么挑安全—BlackBerry手机安全如何选择方法买BlackBerry手机怎么挑安全—BlackBerry手机安全如何选择方法买BlackBerry手机怎么挑安全—BlackBerry手机安全如何选择方法

    黑莓手机安全性取决于系统类型与使用需求。BlackBerry OS封闭性强,适合追求纯净通信的用户;Android+黑莓安全层(如KEYone、KEY2)兼顾开放性与防护,支持DTEK监控、硬件加密、端到端加密通讯及远程擦除功能。需注意BlackBerry OS服务已于2022年终止,老机型无法联网…

    2026年10月1日 • 用户投稿
    1000
  • 跨界爆款内容打法:不会做跨界内容组合,做不出小红书爆款

    跨界爆款内容打法:不会做跨界内容组合,做不出小红书爆款跨界爆款内容打法:不会做跨界内容组合,做不出小红书爆款跨界爆款内容打法:不会做跨界内容组合,做不出小红书爆款跨界爆款内容打法:不会做跨界内容组合,做不出小红书爆款

    做小红书博主最常见的疑问和困扰就是,辛辛苦苦拍摄剪辑的短视频播放量上不去,不能吸引人观看,完播率太低,短视频内容陷入瓶颈没有了创造力,不知道怎么持续性作出爆款视频笔记? 这是因为你没有跨界组合内容的能力,不会短视频跨界爆款内容的打法。 其实归根结底就是一句话,因为内容做不好,所以短视频没流量,因为短…

    2026年10月1日 • 用户投稿
    400
  • 灵狐浏览器高清视频优化入口2025-灵狐浏览器影音版网页登录地址

    灵狐浏览器高清视频优化入口2025-灵狐浏览器影音版网页登录地址灵狐浏览器高清视频优化入口2025-灵狐浏览器影音版网页登录地址灵狐浏览器高清视频优化入口2025-灵狐浏览器影音版网页登录地址灵狐浏览器高清视频优化入口2025-灵狐浏览器影音版网页登录地址

    灵狐浏览器高清视频优化入口位于官网“影音加速”模块,登录后可在个人中心启用智能画质增强功能。用户可通过主站导航栏、播放页工具条、快捷键Ctrl+Shift+V或移动端侧边菜单进入优化界面。平台采用分布式节点调度、预加载引擎和多线程下载技术提升加载速度,支持自适应码率与缓冲设置。视觉方面集成AI修复、…

    2026年10月1日 • 用户投稿
    300
  • 如何使用高级选项重装win10系统?重装win10系统方法

    如何使用高级选项重装win10系统?重装win10系统方法如何使用高级选项重装win10系统?重装win10系统方法如何使用高级选项重装win10系统?重装win10系统方法如何使用高级选项重装win10系统?重装win10系统方法

    电脑使用时间一长,难免会积累大量垃圾文件,虽然可以借助清理软件进行打扫,但总有一些顽固文件难以清除,长期堆积会影响系统运行速度,导致电脑卡顿。面对这种情况,重装系统是一个有效的解决方案,能够显著提升电脑性能。接下来,就为大家详细介绍如何通过高级选项使用光盘重装win10系统。 通过高级选项利用光盘重…

    2026年10月1日 • 用户投稿
    100
  • java使用教程如何使用正则表达式匹配字符串 java使用教程的正则应用基础教程​

    java使用教程如何使用正则表达式匹配字符串 java使用教程的正则应用基础教程​java使用教程如何使用正则表达式匹配字符串 java使用教程的正则应用基础教程​java使用教程如何使用正则表达式匹配字符串 java使用教程的正则应用基础教程​java使用教程如何使用正则表达式匹配字符串 java使用教程的正则应用基础教程​

    在java中使用正则表达式需先通过pattern.compile()编译正则字符串生成pattern对象,再调用其matcher()方法结合目标字符串创建matcher对象;2. matcher对象通过find()查找子串匹配、matches()判断全串匹配、group()获取匹配内容、start(…

    2026年10月1日 • 用户投稿
    500
  • Sublime任务自动化 Sublime定时执行脚本方法

    Sublime任务自动化 Sublime定时执行脚本方法Sublime任务自动化 Sublime定时执行脚本方法Sublime任务自动化 Sublime定时执行脚本方法Sublime任务自动化 Sublime定时执行脚本方法

    sublime text自身不支持定时任务,但可通过操作系统的调度工具实现脚本的定时执行。具体步骤如下:1. 利用sublime的构建系统、宏和插件实现内部自动化;2. 在windows上使用任务计划程序配置定时任务,设置触发器和启动程序;3. 在macos或linux上使用cron编写定时任务命令…

    2026年10月1日 • 用户投稿
    100
  • 谷歌浏览器如何同步书签和设置_谷歌浏览器数据同步功能配置指南

    谷歌浏览器如何同步书签和设置_谷歌浏览器数据同步功能配置指南谷歌浏览器如何同步书签和设置_谷歌浏览器数据同步功能配置指南谷歌浏览器如何同步书签和设置_谷歌浏览器数据同步功能配置指南谷歌浏览器如何同步书签和设置_谷歌浏览器数据同步功能配置指南

    首先检查并登录Google账号确保同步已开启,接着通过chrome://sync-internals/手动触发同步,最后可导出书签HTML文件进行本地传输与导入。 如果您在多台设备上使用谷歌浏览器,但发现书签和设置未能自动更新,可能是同步功能未正确配置或存在延迟。以下是解决此问题的步骤: 本文运行环…

    2026年10月1日 • 用户投稿
    000
  • 云原生落地指南之K8s实战_Java项目基于云原生的部署与管理方法

    云原生落地指南之K8s实战_Java项目基于云原生的部署与管理方法云原生落地指南之K8s实战_Java项目基于云原生的部署与管理方法云原生落地指南之K8s实战_Java项目基于云原生的部署与管理方法云原生落地指南之K8s实战_Java项目基于云原生的部署与管理方法

    java项目在云原生环境中的部署与管理核心在于解耦与自动化,必须先将应用容器化并利用kubernetes实现自动化编排,具体包括通过多阶段构建优化docker镜像以减小体积提升安全性,再通过kubernetes定义deployment、service等资源对象实现服务的弹性伸缩、故障自愈和声明式管理…

    2026年10月1日 • 用户投稿
    900
  • win10谷歌浏览器怎么用谷歌搜索引擎

    win10谷歌浏览器怎么用谷歌搜索引擎win10谷歌浏览器怎么用谷歌搜索引擎win10谷歌浏览器怎么用谷歌搜索引擎win10谷歌浏览器怎么用谷歌搜索引擎

    谷歌浏览器因其便捷性和稳定性受到众多用户的青睐,许多用户都倾向于使用谷歌自带的搜索引擎功能。然而,部分win10系统的用户可能遇到无法正常使用谷歌搜索引擎的问题,那么接下来就为大家介绍如何在win10系统中让谷歌浏览器采用谷歌搜索引擎的方法,赶紧来看看吧! win10谷歌浏览器启用谷歌搜索引擎的操作…

    2026年10月1日 • 用户投稿
    200
  • windows11如何查看系统日志分析电脑问题_windows11系统日志查看与分析方法

    windows11如何查看系统日志分析电脑问题_windows11系统日志查看与分析方法windows11如何查看系统日志分析电脑问题_windows11系统日志查看与分析方法windows11如何查看系统日志分析电脑问题_windows11系统日志查看与分析方法windows11如何查看系统日志分析电脑问题_windows11系统日志查看与分析方法

    通过事件查看器、筛选功能、PowerShell命令和导出日志文件可有效查看和分析Windows 11系统日志,定位系统崩溃、应用无响应等问题原因。 如果您在使用Windows 11时遇到系统崩溃、应用无响应或硬件驱动异常等问题,通过查看系统日志可以获取详细的错误信息和事件记录,帮助您精确定位故障原因…

    2026年10月1日 • 用户投稿
    100
  • 高通孟樸:携手中国汽车产业伙伴 书写智能出行新篇章

    高通孟樸:携手中国汽车产业伙伴 书写智能出行新篇章高通孟樸:携手中国汽车产业伙伴 书写智能出行新篇章高通孟樸:携手中国汽车产业伙伴 书写智能出行新篇章高通孟樸:携手中国汽车产业伙伴 书写智能出行新篇章

    2025年6月26日至27日,“2025高通汽车技术与合作峰会”在苏州顺利举办,本次大会围绕“我们一起,行稳智远”的主题展开,聚焦智能汽车产业未来发展的新热点、新趋势与新机遇。6月27日,在峰会主论坛上,高通中国区董事长孟樸发表了热情洋溢的欢迎致辞。他表示,高通将继续以“连接+计算+ai”为核心战略…

    2026年10月1日 • 用户投稿
    300
  • AMD不是受害者 NVIDIA与Intel合作带来三赢:原因有二

    AMD不是受害者 NVIDIA与Intel合作带来三赢:原因有二AMD不是受害者 NVIDIA与Intel合作带来三赢:原因有二AMD不是受害者 NVIDIA与Intel合作带来三赢:原因有二AMD不是受害者 NVIDIA与Intel合作带来三赢:原因有二

    9月20日消息,nvidia向intel投资50亿美元的重磅合作仍在持续引发行业震荡,这场“双英联手”正为cpu、gpu及ai市场带来前所未有的变局。 目前普遍观点认为,此次合作是NVIDIA与Intel的双赢之举:NVIDIA得以借助Intel的x86生态进一步拓展AI计算版图,而Intel则获得…

    2026年10月1日 • 用户投稿
    100
  • 谷歌浏览器页面文字显示不清晰如何修复

    谷歌浏览器页面文字显示不清晰如何修复谷歌浏览器页面文字显示不清晰如何修复谷歌浏览器页面文字显示不清晰如何修复谷歌浏览器页面文字显示不清晰如何修复

    当您发现谷歌浏览器中的网页字体显示模糊、边缘不清时,这通常与您电脑的显示设置、浏览器自身的渲染机制或缩放配置有关。本文将通过几个关键步骤,从系统层面到浏览器内部设置,引导您进行调整,以恢复清晰锐利的字体显示效果。 调整系统ClearType文本设置 1、此方法主要适用于Windows系统用户。您可以…

    2026年10月1日 • 用户投稿
    000
  • 使用线性搜索在两个 ArrayList 中查找元素

    使用线性搜索在两个 ArrayList 中查找元素使用线性搜索在两个 ArrayList 中查找元素使用线性搜索在两个 ArrayList 中查找元素使用线性搜索在两个 ArrayList 中查找元素

    本文介绍了如何在 Java 中使用线性搜索算法比较两个字符串类型的 ArrayList,以判断一个列表(例如购物清单)中的所有元素是否都存在于另一个列表(例如食品储藏室清单)中。我们将探讨如何通过循环遍历和条件判断来实现此功能,并提供使用 HashSet 优化搜索效率的替代方案。 线性搜索实现 线性…

    2026年10月1日 • 用户投稿
    000
  • 买一加手机怎么挑刷新率—一加手机刷新率如何选择方法

    买一加手机怎么挑刷新率—一加手机刷新率如何选择方法买一加手机怎么挑刷新率—一加手机刷新率如何选择方法买一加手机怎么挑刷新率—一加手机刷新率如何选择方法买一加手机怎么挑刷新率—一加手机刷新率如何选择方法

    选一加手机刷新率需结合屏幕技术、使用习惯和耗电,Ace系列如Ace 5至尊版支持144Hz游戏优化,一加13等旗舰支持120Hz加LTPO动态调节,中端机型或为90Hz/固定120Hz无智能调节;购机时应查官网参数确认刷新率与自适应功能;设置中可选60Hz至144Hz档位,推荐日常用智能模式平衡流畅…

    2026年10月1日 • 用户投稿
    000
  • Sublime代码格式化插件推荐|保持统一风格更专业

    Sublime代码格式化插件推荐|保持统一风格更专业Sublime代码格式化插件推荐|保持统一风格更专业Sublime代码格式化插件推荐|保持统一风格更专业Sublime代码格式化插件推荐|保持统一风格更专业

    推荐使用html-css-js prettify和sublimejsprettier两款插件格式化sublime text 3代码。1.html-css-js prettify专为前端设计,支持html、css、js格式化,提供自定义配置、快捷键绑定及标签修正功能,但对vue或react语法识别较弱…

    2026年10月1日 • 用户投稿
    100
  • win10自带的groove音乐播放器无法播放的解决方法

    win10自带的groove音乐播放器无法播放的解决方法win10自带的groove音乐播放器无法播放的解决方法win10自带的groove音乐播放器无法播放的解决方法win10自带的groove音乐播放器无法播放的解决方法

    在win10系统中,groove音乐播放器是预装的软件之一,但有时用户可能会遇到无法正常播放音乐的问题。针对这一情况,以下是一些解决办法,希望能帮助到有需要的朋友。 解决win10系统自带groove音乐播放器无法播放的方法: 首先,在开始菜单上右击鼠标,然后选择【设备管理器】选项; 进入设备管理器…

    2026年10月1日 • 用户投稿
    100
  • 根据字母等级计算绩点并输出

    根据字母等级计算绩点并输出根据字母等级计算绩点并输出根据字母等级计算绩点并输出根据字母等级计算绩点并输出

    本文旨在指导读者如何编写一个Java程序,该程序接受用户输入的字母等级,并根据等级返回相应的绩点。程序包含异常处理机制,能够有效处理无效的字母等级输入,并输出相应的错误提示信息,确保程序的健壮性和用户体验。 程序实现 以下是一个Java程序的示例,它实现了根据用户输入的字母等级计算并输出绩点的功能。…

    2026年10月1日 • 用户投稿
    100

发表回复

登录后才能评论
关注微信