首先很抱歉,因为搬家,最近太多事情要处理,致使文章更新比较慢。golang
这篇文章,咱们讲Go中的异常处理。网络
Go提供了两个内置函数 panic()和recover()用于异常处理。函数
Go中,对异常处理的总体原则是:多用errors包,少用panic。spa
对于可预见的错误,好比网络链接失败等,通常都使用errors,只有重大错误才会使用panic。code
记住一个大原则:panic会致使程序直接挂掉,除非调用了recover方法。blog
在函数内部调用 panic 会当即终止当前函数的执行,由当前调用栈逐层返回,一直到最顶层的 main 函数或是被某一层的 recover 捕捉到。it
看例子:io
package mainasm
import (class
"fmt"
)
func main() {
fmt.Println("Start main")
sub()
fmt.Println("End main")
}
func sub() {
fmt.Println("Before panic")
panic("golang_everyday")
fmt.Println("After panic")
}
执行结果:
Start main
Before panic
panic: golang_everyday
goroutine 1 [running]:
main.sub()
/Users/baiyuxiong/go/src/baiyuxiong.com/demo/panic.go:18 +0x124
main.main()
/Users/baiyuxiong/go/src/baiyuxiong.com/demo/panic.go:10 +0xdf
goroutine 2 [runnable]:
runtime.forcegchelper()
/usr/local/go/src/runtime/proc.go:90
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2232 +0x1
goroutine 3 [runnable]:
runtime.bgsweep()
/usr/local/go/src/runtime/mgc0.go:82
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2232 +0x1
goroutine 4 [runnable]:
runtime.runfinq()
/usr/local/go/src/runtime/malloc.go:712
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2232 +0x1
exit status 2
能够看到,panic以后,程序中止继续执行,一层层的退出直到main,退出了整个程序,而后打印了堆栈信息。
若是咱们在sub函数中,使用defer进行recover:
package main import ( "fmt" ) func main() { fmt.Println("Start main") sub() fmt.Println("End main") } func sub() { defer handler() fmt.Println("Before panic") panic("golang_everyday") fmt.Println("After panic") } func handler() { if err := recover(); err != nil { fmt.Println("recover msg: ", err) } else { fmt.Println("recover ok") } }
执行结果:
Start main
Before panic
recover msg: golang_everyday
End main
能够看到,sub函数没有执行完,panic后执行了defer就返回到上层main函数了,可是main函数执行结束了。
这是由于recover阻止了异常的继续传播。他将panic限制在了必定的范围内。
这就像屋子里丢了一炸弹(panic产生了),原本全部人都要挂掉的(panic传递到main,整个程序退出),可是有一个叫recover的小伙子很是勇敢,duang!!!抱到炸弹上去了,损失就控制在必定范围内了,若是这小伙子越早的抱到炸弹,受伤的人就会越少。