Go语言之panic和recover

ZhDavis · · 1675 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

转自“灰子学技术”,原文链接:https://mp.weixin.qq.com/s/cfPY26_zOzFFSuPbElDU-Q

写在前面的话:

panic是Go语言中,用于终止程序的一种函数,往往用在下面两种情况:1)程序出现了很大的故障,例如不能在提供服务了。2)程序在运行阶段碰到了内存异常的操作,例如空指针的取值,改写只读内存等。

对于panic来说,1)场景往往是主动调用; 2)场景则是被动调用,panic一旦产生之后,会将堆栈里面的数据dump出来,这样就方便了开发人员来定位问题。

recover是用来截获panic异常信息的,截获了之后,可以控制程序跳过panic的地方继续执行。

本文笔者主要分享下,调用panic之后都做了哪些操作,以及recover使用之后的效果。

1. panic使用介绍

panic一旦触发之后,会按照下面的顺序来做处理:

1)panic开始的地方启动终止程序操作。

2)调用当前触发panic函数里面的defer函数。

3)返回该函数的调用方,当作异常返回来处理,所以这一步也会调用调用方函数的defer,一直到没有调用方为止。

4)打印panic的信息。

5)打印堆栈跟踪信息,也就是我们看到的函数调用关系。

6)终止程序。

例子:

结果分析:通过输出结果我们可以看出,1)2调用了panic开始了panic的操作, 3出不在执行,故没有打印。2)执行testPanic中的defer函数,输出了"testPanic exit!" 。3) 接着,返回到调用方main函数,当作异常终止,调用main中的defer函数,打印"main exit!",main中的6处代码也被跳过执行。 4) 打印panic触发时的错误信息"trigger panic!" 。5)打印panic的调用堆栈信息,这里是从触发panic的点开始的,一层层往上调用。6)退出程序。

2. recover使用介绍

recover是go提供的一个用来截获panic信息,重新获取协程控制的函数。它的使用,有两点需要注意,1)recover只能在defer函数中使用。2)recover的使用必须于触发panic的协程是同一个协程才行。

例子1,同一个协程中:

结果分析:通过调用recover之后的结果来看,panic被1处的recover成功截获,只是3处到代码没有执行而已,对于调用testPanic的main函数后续代码都被执行了,"main end!"信息也被打印出来了。

例子2,panic和recover在不同协程中,不能恢复

结果分析:通过输出结果可以看出,就算我们在4处调用了rcover,但是panic也没有被截获,原因就是panic在子协程中,而recover在主协程中,recover不能跨协程截获panic信息。

3.补充知识:

  对于panic显示的函数堆栈调用关系,debug.PrintStack()也可以做到,它就是用来打印函数的堆栈调用关系的, 例子如下所示:

下面是panic和recover两个函数的解释说明:https://golang.org/src/builtin/builtin.go?h=panic#L232

灰子学技术:

 

 


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1675 次点击  ∙  1 赞  
加入收藏 微博
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传