這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
53.蛤蟆筆記go語言——defer,panic,recover使用情境
defer
defer 調用的函數將被暫時儲存到調用列表中. 儲存的調用列表在當前環境返回的時候被執行. Defer 一般可以用於簡化代碼, 執行各種清理操作.
Defer語句的行為簡單且可預測. 有三個基本原則:
1. 當defer調用函數的時候, 函數用到的每個參數和變數的值也會被計算
2. Defer調用的函數將在當前函數返回的時候, 以後進先出的順序執行.
3. Defer調用的函數可以在返回語句執行後讀取或修改命名的傳回值. 利用該特性, 我們可以方便修改函數的錯誤傳回值.
Panic
Panic 是一個內建的函數: 停止當前控制流程, 然後開始panicking. 當F函數調用panic, F函數將停止執行後續的普通語句, 但是之前的defered函數調用仍然被正常執行, 然後再返回到F的調用者. 對於F函數的調用者, F 的行為和直接調用panic函數類似. 以上的處理流程會一直沿著調用棧回朔, 直到當前的goroutine返回引起程式崩潰! Panics可以通過直接調用panic方式觸發, 也可以由某些執行階段錯誤觸發, 例如: 數組的越界訪問.
recover
Recover 也是一個內建函數: 用於從 panicking 恢複. Recover 和 defer 配合使用會非常有用. 對於一個普通的執行流程, 調用recover將返回nil, 也沒有任何效果. 但如果當前goroutine處於 panicking狀態, recover調用會捕獲觸發panic時的參數, 並且恢複到正常的執行流程.
範例程式碼如下:
packagemain
import"fmt"
funcmain(){
f()
fmt.Println("Returnednormallyfromf.")
}
funcf(){
deferfunc(){
ifr:=recover();r!=nil{
fmt.Println("Recoveredinf",r)
}
}()
fmt.Println("Callingg.")
g(0)
fmt.Println("Returnednormallyfromg.")
}
funcg(iint){
ifi>3{
fmt.Println("Panicking!")
panic(fmt.Sprintf("%v",i))
}
deferfmt.Println("Defering",i)
fmt.Println("Printinging",i)
g(i+1)
}
執行如下:
Calling g.
Printing in g 0
Printing in g 1
Printing in g 2
Printing in g 3
Panicking!
Defer in g 3
Defer in g 2
Defer in g 1
Defer in g 0
Recovered in f 4
Returnednormally from f.
defer 語句(不管是否包含panic 和 recover)提供了一種不同尋常且十分強大的控制流程機制. 它可以用於類比一些其他語言中的某些特殊的文法結構.