在我们面试时会遇到这样的问题,问执行后的结果
func main() {
defer_call1()
}
func defer_call1() {
defer func() { fmt.Println("打印前") }()
defer func() { fmt.Println("打印中") }()
defer func() { fmt.Println("打印后") }()
panic("触发异常")
}
这个正确的返回结果是
打印后
打印中
打印前
panic: 触发异常
出现这个情况就会有想defer和painc到底哪个是先执行,为什么优先打印出了defer之后再打印了painc
先来公布答案,是先执行到了painc之后再执行的defer,defer 的执行顺序是后进先出。当出现 panic 语句的时候,会先按照 defer 的后进先出的顺序执行,最后才会执行panic
让我来做个测试,这个测试中使用到了recove()这个函数
1. Go语言提供了内置函数recover(),一般在defer语句中调用,用于捕获panic异常,使程序从panic中回复,并返回panic value。
2.导致panic异常的函数不会继续运行,但是能正常返回,这意味着调用recover()的函数的上一级调用者可以继续往下执行代码,而不是中断程序运行。
3.利用recover处理panic时,defer必须在panic之前声明,否则当panic时,recover无法捕获到panic。
下面我们来看这个例子:
package main
import (
"fmt"
)
//1. defer 的执行顺序是后进先出。当出现 panic 语句的时候,会先按照 defer 的后进先出的顺序执行,最后才会执行panic
func main() {
defer_call()
}
func defer_call() {
defer func() { fmt.Println("打印前") }()
defer func() { fmt.Println("打印中") }()
defer func() { fmt.Println("打印后") }()
defer func() {
fmt.Println("我的打印前")
err := recover()
if err != nil {
fmt.Println("捕获painc")
fmt.Println(err)
}
fmt.Println("我的打印后")
}()
defer_call_two()
}
func defer_call_two() {
defer func() { fmt.Println("第二个方法") }()
panic("触发异常1")
panic("触发异常2")
fmt.Println("e")
}
其结果是
第二个方法
我的打印前
捕获painc
触发异常1
我的打印后
打印后
打印中
打印前
从结果中可以明显看出,先是执行到了异常之后触发recover(),最后执行了defer方法