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信息按壓入棧的順序輸出