iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 19
1
自我挑戰組

30天學會Golang系列 第 19

day19 - 錯誤處理(續)

  • 分享至 

  • xImage
  •  

大家好,今天鐵人賽第十九天。昨天簡單說明了如何自訂錯誤,今天來講錯誤處理的相關語法,包含 deferpanicrecover

defer

defer 是延遲執行的關鍵字,可以將其後面的程式碼延後至函式結束時執行。

func main() {
	fmt.Println("defer begin")

	defer fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)

	fmt.Println("defer end")
}

/* 執行結果:
defer begin
defer end
3
2
1
*/

多個 defer 的程式碼的執行順序是相反的,最先被 defer 的程式碼會在最後被執行。

panic

使用 panic 會直接造成系統崩潰、服務中斷,就像是 Java/C# 中的 throw exception ,如下:

func main() {
	panic("crash")
	fmt.Println("hello,world")
}

執行後就會產生錯誤訊息,而且不會執行後面的程式碼:

panic: crash

但是如果在 panic 之前就 defer 的程式碼,會在崩潰前執行:

func main() {
	defer fmt.Println("defer hello")
	panic("crash")
	fmt.Println("hello,world")
}

執行結果:

defer hello
panic: crash

我們可以在執行一個可能會出錯的函式時使用 panic,當這個函式回傳的錯誤不是 nil 時直接讓系統崩潰,防止之後造成更大的錯誤。

func main() {
	// 呼叫函式同時回傳結果與錯誤
	value, error := foo()
    
	// 檢查錯誤
	if error == nil {
		fmt.Println(value)
	} else {
		panic(error.Error())  // 系統中斷,印出錯誤訊息
	}
    
    // 其他程式碼
}

recover

recover 可以捕捉到系統或手動產生的 panic 錯誤,回復系統以避免程序崩潰。recover 必須和 defer 配合使用,如下:

func main() {
	defer func() {
		err := recover()
		fmt.Println(err)
	}()

	panic("crash")

	fmt.Println("hello,world")
}

/* 執行結果:
crash
*/

執行後不最造成系統崩潰,而是繼續執行 recover 後面的程式碼,但是不會繼續執行 panic 後面的程式碼。

我們可以用 recover 模擬 try-catch 機制,由於go語言的錯誤處理是函式層級,因此我們需要定義一個 try 函式,代替主函式來執行可能出錯的函式,如下:

// 定義一個接受函式參數的函式,在發生錯誤時會捕捉錯誤防止崩潰
func try(action func()) {
	defer func() {
		err := recover()
		fmt.Println(err)
	}()

    // 執行方法
	action()
}

func main() {
	// 嘗試執行可能出錯的函式
	try(func() {
		panic("crash")
	})

    // 即使 try 裡面函式出錯依然可以往下執行
	fmt.Println("hello,world")
}

/* 執行結果:
crash
hello,world
*/

小結

今天大致上說明了 deferpanicrecover 用法,透過這三個語法同樣也能做出良好的錯誤處理程序。


上一篇
day18 - 錯誤處理
下一篇
day20 - 字串操作
系列文
30天學會Golang30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言