首先很抱歉,因爲搬家,最近太多事情要處理,致使文章更新比較慢。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!!!抱到炸彈上去了,損失就控制在必定範圍內了,若是這小夥子越早的抱到炸彈,受傷的人就會越少。