其他分享
首页 > 其他分享> > Golang的panic和recover

Golang的panic和recover

作者:互联网

Golang的panic和recover

panic

  关键字panic的作用是制造一次宕机,宕机就代表程序运行终止,但是已经“生效”的延迟函数仍会执行(即已经压入栈的defer延迟函数,panic之前的)。

  为什么要制造宕机呢?是因为宕机不容易遇到?还是因为程序有错就是直接报错,都没有执行,哪来的宕机?

  Go程序设计语言中这样提到:如果碰到“不可能发生的”的状况,宕机是最好的处理方式。这个“不可能发生的”状况很难理解,不过可以这样想:一个机器人的能源供应,可能依靠太阳能,可能依靠电能,但是如果靠吃饭解决,那么这肯定就不可思议了,这时候就应该触发一次宕机。

关于panic,下面是一个例子:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 package main import "fmt" func main(){     defer func(){         fmt.Println("aaaaaa")     }()     fmt.Println("bbbbbb")     fmt.Println("cccccc")     panic("hahahaha")     fmt.Println("ddddd")     defer func(){         fmt.Println("eeeeeeee")     }() }

  首先顺序执行,会先将第一个defer延迟函数“入栈”(这里称为入栈是为了便于理解),然后输出“bbbbbbb",”cccccccc”,此时使用panic来触发一次宕机,panic接受一个任意类型的参数,会将该字符串输出,用作提示信息,之后的代码不再执行,所以后面的dddddd不会输出,而且第二个defer延迟函数也不会“入栈”,因为panic之后的代码不会继续执行,程序现在只会运行已经“入栈”的defer延迟函数,输出aaaaaa,在最后,会输出此次触发宕机的一些信息,所以执行结果如下:

1 2 3 4 5 6 7 8 9 bbbbbb cccccc aaaaaa panic: hahahaha   goroutine 1 [running]: main.main()     /Users/root/Desktop/test.go:9 +0xf1 exit status 2

  为什么不执行panic后面的defer,其实这个很好理解,比如,有两次读文件操作,那么每一次读文件之后都是用defer关闭文件,如果第一次读文件就引发了panic异常,而第二次读文件操作还没开始,也就是说还没有打开文件,那么调用第二个defer来关闭第二个文件,有意义吗?应该是只关闭第一个打开的文件,对吧?也就是调用第一个defer。

recover

   recover从英文的意思上就知道是恢复,那么这个恢复是恢复什么呢?是恢复运行状态,继续运行?还是恢复到宕机之前?

  其实,recover在英文中指的是受伤的愈合,防止伤口进一步感染。伤是愈合了,但是伤了始终是伤了,愈合只不过是事后处理而已。所以golang中的recover也只是发生宕机之后的后事处理。

  所以这里的recover只是用来接收panic触发的宕机,如果panic触发宕机,传给panic的任意类型的参数,recover会接收到这个参数,recover获取到值之后才知道发生了宕机;相反,如果程序中的recover没有获取到值,则代表没有发生宕机,那么recover的值就为nil,通过这个可以来进一步处理后事。

  前面已经提到panic的时候,已经说了,一旦发生宕机,其后的代码是不会执行的,但是会调用位于panic代码所在的哪一行之前的defer延迟函数,所以说这个特性就决定recover应该用在defer函数中,否则一旦发生宕机,除了defer延迟函数中的语句还能执行外,其他的语句都是不能执行的。

  如果触发宕机,panic的错误信息会显示,如果有recover时,则信息会被recover截获,于是错误信息就不会显示,转而进行下一步操作。

下面是一个简单的示例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package main import "fmt" func main() {     defer func() {         if info := recover(); info != nil {             fmt.Println("触发了宕机", info)         else {             fmt.Println("程序正常退出")         }     }()     fmt.Println("bbbbbb")     fmt.Println("cccccc")     panic("fatal error")     fmt.Println("ddddd")     defer func() {         fmt.Println("eeeeeeee")     }() }

  运行结果如下:

1 2 3 bbbbbb cccccc 触发了宕机 fatal error

  

转自  https://www.cnblogs.com/-beyond/p/8394691.html

标签:defer,宕机,fmt,Golang,Println,recover,panic
来源: https://www.cnblogs.com/rxbook/p/15343919.html