思考题: 下列程序输出什么?
package main
import "fmt"
func main() {
fmt.Println("a")
if err := recover(); err != nil {
fmt.Println(err)
}
panic("panic")
fmt.Println("b")
if err := recover(); err != nil {
fmt.Println(err)
}
fmt.Println("c")
}
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
运行结果:
a
panic: panic
goroutine 1 [running]:
main.main()
recover.go:11 +0x105
exit status 2
上面程序中两个recover调用都不能捕获任何异常。在第一个recover调用执行时,函数必然是在正常的非异常执行流程中,这时候recover调用将返回nil。发生异常时,第二个recover调用将没有机会被执行到,因为panic调用会导致函数马上执行已经注册defer的函数后返回(不再执行panic后面的代码)。
func main() {
fmt.Println("a")
defer func() {
if err := recover(); err != nil {
fmt.Println("b")
fmt.Println(err)
}
fmt.Println("c")
}()
panic("panic")
fmt.Println("d")
}
输出:
a
b
panic
c
思考以下程序运行结果:
func main() {
fmt.Println("a")
defer func() {
func() {
if err := recover(); err != nil {
fmt.Println("b")
fmt.Println(err)
}
fmt.Println("c")
}()
}()
panic("panic")
fmt.Println("d")
}
,
,
,
,
,
,
,
运行结果:
a
c
panic: panic
goroutine 1 [running]:
main.main()
recover.go:96 +0xb7
exit status 2
思考以下程序运行结果:
func main() {
fmt.Println("a")
defer func() {
defer func() {
if err := recover(); err != nil {
fmt.Println("b")
fmt.Println(err)
}
}()
}()
panic("panic")
fmt.Println("d")
}
,
,
,
,
,
,
,
运行结果:
a
panic: panic
goroutine 1 [running]:
main.main()
recover.go:78 +0xb7
exit status 2
思考以下程序运行结果:
func main() {
fmt.Println("a")
defer func() {
fmt.Println("m")
}()
defer func() {
defer func() {
fmt.Println("n")
}()
if err := recover(); err != nil {
fmt.Println("b")
fmt.Println(err)
}
fmt.Println("c")
defer func() {
fmt.Println("o")
}()
}()
defer func() {
fmt.Println("x")
}()
panic("panic")
fmt.Println("d")
}
,
,
,
,
,
,
,
运行结果:
a
x
b
panic
c
o
n
m
recover函数所在栈栈必须要和有异常的栈帧只隔一个栈帧,recover函数才能正常捕获异常。换言之,recover函数捕获的是祖父一级调用函数栈帧的异常(刚好可以跨越一层defer函数)!
OK:
func myfunc() {
recover()
}
func main() {
defer myfunc()
panic("errrrrrrrrror")
}
ERROR:
func main() {
// 无法捕获异常
defer recover()
panic("errror")
}