Go异常处理defer panic recover
概述
异常处理功能犹如 try … catch … finally …
defer
- defer主要用于函数体中,预先定义函数返回前最后执行的语句。扮演finally的角色。如用于文件或连接关闭
func d() {
f, err := os.Open("test.txt")
if err != nil {
// handle error
fmt.Println("error")
}
defer f.Close() // 在这里可以避免忘记文件关闭,尤其在复杂的逻辑判断业务处理中,容易遗漏文件关闭操作。
// do something
}
- 多个 defer 定义的操作将压入栈中,从栈顶按顺序执行
func d() {
for i := 0; i < 4; i++ {
defer fmt.Println(i)
}
}
结果
3
2
1
0
- defer 定义的函数接收的参数值是当前值。
这个很好理解,函数接收的值是变量的值拷贝,当前拷贝作为参数传入defer定义的函数,自然就与当前值一致。
func d() {
i := 1
defer func(i int) { fmt.Println(i) }(i) // 传入当前 i 值, i==1
i += 1
fmt.Println(i) // i == 2
}
结果:
2
1
- defer 定义的信息是在return前执行
func d() (i int) {
defer func() { i++ }()
k := 1
return k // 最后返回的值是 2;
}
上面执行的顺序是:
k := 1 // 1
i = k // 1
i++ // 2
return i // 2
panic
- panic 是一个build-in函数
- panic 类似与exception,将异常抛出,执行defer程序,之后退出当前函数,exit status 2。
- 如果异常没有被进一步收集处理,则将一直退出直至退出整个程序
recover
- recover 是一个build-in函数
- recover用来捕捉异常,并处理相关异常,并可以让上一级函数继续执行。
- recover必须定义在defer中,当发生panic并开始执行defer时,recover进行异常收集处理
func f(a, b int) int {
defer func() {
if r := recover(); r != nil {
fmt.Println("recover")
} else {
fmt.Println("nothing")
}
}()
fmt.Println(a) // 按顺序输出
if a > 10 {
panic("panic")
}
f(b, a+b)
return 1
}
func main(){
f(0, 1)
}
执行结果
0
1
1
2
3
5
8
13 // a 按顺序输出
recover // panic被处理,所以不输出panic,只输出recover
nothing
nothing
nothing
nothing
nothing
nothing
nothingc // defer信息按压入栈的顺序输出