Go语言之panic和recover

2020-04-02 21:16:02 浏览数 (1)

写在前面的话:

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


0 人点赞