Go異常處理defer panic recover

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

參考

https://blog.golang.org/defer-panic-and-recover

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章