這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
目錄
摘要
defer,defer 棧,改變傳回值,panic,recover
defer 與異常處理
概述
- Go 沒有
try..catch 這種異常機制,而是使用 panic 和 recover。
panic 在任何地方都可以執行,recover 只有在 defer 調用的函數中才有效。
defer
defer 用於定義在函數執行結束後執行的語句
- 多個
defer 會形成 defer 棧,後定義的 defer 語句會被最先調用
- 即使函數發生嚴重錯誤也會執行
- 通過與匿名函數配合可以在 return 之後修改結果
定義多個 defer
func testDefer() { fmt.Println("a") defer fmt.Println("b") defer fmt.Println("c") defer func() { fmt.Println("d") }()}testDefer() //a d c b
改變傳回值
由於 defer 在函數執行結束後執行,所以可以用於改變命名傳回值的值
錯誤的用法
func changeResult(x int) int { defer func() { x++ //返回的值,改變變數沒有用 }() return x}x = changeResult(8)fmt.Println("x", x) //x 8
正確的用法
func changeResult2(x int) (result int) { defer func() { result++ }() return x}x = changeResult2(8)fmt.Println("x", x) //x 9
panic 與 recover
panic 用於向上傳遞異常,執行在 defer 之後,表示非常嚴重不可恢複的異常,會導致程式掛掉
recover 可以對 panic 進行捕獲,使 panic 停止向上傳遞
使用 panic
func one() { fmt.Println("func one") }func two() { fmt.Println("func two") }func broken() { one() panic("func broken with Panic") two()}broken()
輸出
func onepanic: func broken with Panic異常訊息...程式中斷
使用 recover
func one() { fmt.Println("func one") }func two() { fmt.Println("func two") }func catch() { one() defer func() { if err := recover(); err != nil { fmt.Println("func catch with Recover") } }() panic("func broken with Panic") two()}catch()
輸出
func onefunc catch with Recover
注意
defer 需要放在 panic 之前定義
recover 之後,邏輯並不會恢複到 panic 那個點去,函數還是會在 defer 之後返回