Go进阶07 defer,panic,recover

2017-09-04 17:39:56
概念
  • defer
    在函数返回前执行一些操作,表达式通常用来处理一些清理和释放资源的操作
  • panic
    表示非常严重的不可恢复的错误,panic一般会导致程序挂掉(除非recover),重要的一点是,即使函数执行的时候panic了,函数不往下走了,运行时并不是立刻向上传递panic,而是到defer那,等defer的东西都跑完了,panic再向上传递
  • recover
    Go语言提供了recover内置函数,一旦panic,逻辑就会走到defer那,那我们就在defer那等着,调用recover函数将会捕获到当前的panic(如果有的话),被捕获到的panic就不会向上传递了
    要注意的是,recover之后,逻辑并不会恢复到panic那个点去,函数还是会在defer之后返回
用法

首先我们来看下defer,在官方的文档中看到defer的执行顺序是逆序的,也就是先进后出的顺序:

1
2
3
4
5
6
for i :=0; i< 5; i++ {
defer fmt.Printf("%d ", i)
}

[tiger@bogon go]$ go run defer.go
4 3 2 1 0

如何从panic中恢复呢? recover()函数用于获取/拦截panic,仅当在一个defer函数中被完成时.下面来看三个例子
错误的:

1
2
3
4
5
6
7
8
package main
import fmt
func main() {
recover() //don't do anything
panic("not good")
recover() //will not be executed
fmt.Println("ok")
}

正确的:

1
2
3
4
5
6
7
8
9
package main
import fmt
func main() {
defer func() {
fmt.Println("recovered:",recover())
}()

panic("not good")
}

失败的:

1
2
3
4
5
6
7
8
9
10
11
12
package main
import fmt
func doRecover(){
fmt.Println("recovered =>", recover()) //prints: recovered => <nil>
}

func main() {
defer func() {
doRecover() //panic is not recovered
}()
panic("not good")
}

总结

defer可以多次,这样形成一个defer栈,后defer的语句在函数返回时将先被调用
panic一般会导致程序挂掉
recover()的调用仅当它在defer函数中被直接调用时才有效
recover之后,逻辑并不会恢复到panic那个点去,函数还是会在defer之后返回


您的鼓励是我写作最大的动力

俗话说,投资效率是最好的投资。 如果您感觉我的文章质量不错,读后收获很大,预计能为您提高 10% 的工作效率,不妨小额捐助我一下,让我有动力继续写出更多好文章。