panic
关键字panic的作用是制造一次宕机,宕机就代表程序运行终止,但是已经“生效”的延迟函数仍会执行(即已经压入栈的defer延迟函数,panic之前的)。
为什么要制造宕机呢?是因为宕机不容易遇到?还是因为程序有错就是直接报错,都没有执行,哪来的宕机?
Go程序设计语言中这样提到:如果碰到“不可能发生的”的状况,宕机是最好的处理方式。这个“不可能发生的”状况很难理解,不过可以这样想:一个机器人的能源供应,可能依靠太阳能,可能依靠电能,但是如果靠吃饭解决,那么这肯定就不可思议了,这时候就应该触发一次宕机。
关于panic,下面是一个例子:
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,在最后,会输出此次触发宕机的一些信息,所以执行结果如下:
bbbbbb cccccc aaaaaa panic: hahahaha goroutine 1 [running]: main.main() /Users/root/Desktop/test.go:9 +0xf1 exit status 2
recover
recover从英文的意思上就知道是恢复,那么这个恢复是恢复什么呢?是恢复运行状态,继续运行?还是恢复到宕机之前?
其实,recover在英文中指的是受伤的愈合,伤是愈合了,但是伤了始终是伤了,愈合只不过是事后处理而已。
所以这里的recover只是用来接收panic出发的宕机,如果panic触发宕机,传给panic的任意类型的参数,这个参数就会传给recover,recover获取到值之后才知道发生了宕机,
package main import "fmt" func main(){ defer func(){ info := recover() fmt.Println("触发了宕机",info) }() fmt.Println("bbbbbb") fmt.Println("cccccc") panic("fatal error") fmt.Println("ddddd") defer func(){ fmt.Println("eeeeeeee") }() }
运行结果如下:
bbbbbb cccccc 触发了宕机 fatal error