Go编程中recover源码是什么


本篇内容介绍了“Go编程中recover源码是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!就像我们之前针对panic做的一样,我们也写一段简单的代码,通过其汇编码尝试找出内置函数r开发云主机域名ecover()的底层实现。编写以下简单的代码,并保存在名为compile.go的文件里:然后使用以下命令编译代码:接着根据代码行号找出recover()语句对应的汇编码:我们可以看到recover()函数调用被替换成了runtime.gorecover()函数。runtime.gorecover()实现源码位于src/runtime/panic.go。runtime.gorecover()函数实现很简短:短短的代码,蕴含的信息量却很大。 它可以解释以下问题:recover()到底是如何恢复panic的?为什么recover()一定要在defer()函数中才生效?假如defer()函数中调用了函数A(),为什么A()中的recover()不能生效?runtime.gorecover()函数通过协程数据结构中的_panic得到当前的panic的实例(上面代码中p),如果当前panic的状态支持recover,给该panic实例标记recovered状态(p.recovered = true),最后返回panic()函数的参数(p.arg)。另外,当前执行recover()的defer函数是被runtime.gopanic()执行的,defer函数执行结束以后,runtime.gopanic()函数中会检查panic实例的recovered状态,如果发现panic被恢复,runtime.gopanic()将会结束当前panic流程,将程序流程恢复正常。通过代码的if语句可以看到需要满足四个条件才可以恢复panic,且四个条件缺一不可:p != nil:必须存在panic;!p.goexit:非runtime.Goexit();!p.recovered:panic还未被恢复;argp == uintptr(p.argp):recover()必须被defer()直接调用。当前协程没有产生panic时,协程结构体中panic的链表为空,不满足恢复条件。当程序运行runtime.Goexit()时也会创建一个panic实例,会标记该实例的goexit属性为true,但该类型的panic不能被恢复。假设函数包含多个defer函数,前面的defer通过recover()消除panic后,函数中剩余的defer仍然会执行,但不能再次recover(),如下代码所示,函数第一行defer中的recover()将返回nil。细心的读者或许会发现,内置函数recover()没有参数,runtime.gorecover()函数却有参数,为什么呢? 这正是为了限制recover()必须被defer()直接调用。runtime.gorecover()函数的参数为调用recover()函数的参数地址,通常是defer函数的参数地址,同地_panic实例中也保存了当前defer函数的参数地址,如果二者一致,说明recover()被defer函数直接调用。举例如下:通过以上源码的分析,我们可以很好地回答以下问题了:为什么recover()一定要在defer()函数中才生效?假如defer()函数中调用了函数A(),为什么A()中的recover()不能生效?如果recover()不在defer()函数中,那么recover()可能出现在panic()之前,也可能出现在panic()之后,出现在panic()之前,因为找不到panic实例而无法生效,出现在panic()之后,代码没有机会执行,所以recover()必须存在于defer函数中才会生效。通过上面的分析,从代码层面我们理解了为什么recover()函数必须被defer直接调用才会生效。但为什么要有这样的设计呢?笔者也没有找到官方关于此设计的资料,不过笔者认为此设计非常合理。考虑下面的代码:有时我们会在代码里显式地触发panic,同时往往还会在defer函数里调用第三方包清理资源,如果第三方包也使用了recover(),那么我们触发的panic将会被拦截,而且这种拦截可能是非预期的,并不我们期望的结果。“Go编程中recover源码是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注开发云网站,小编将为大家输出更多高质量的实用文章!

相关推荐: 2021年DevOps的趋势有哪些

这篇“2021年DevOps的趋势有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“2021年DevOps的趋势有哪些”文章吧。“从单体架构迁…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

Like (0)
Donate 微信扫一扫 微信扫一扫
Previous 05/16 13:06
Next 05/16 13:06

相关推荐