Golang的異常處理實戰篇
作者:尹正傑
版權聲明:原創作品,謝絕轉載!否則將追究法律責任。
Go語言的異常捕獲要比Python中簡單的多,它沒有Python中那么多復雜的異常類型及繼承體系。接下來我們來一起體驗一下Golang的異常處理。
一.代碼運行時出錯應該怎樣處理呢?
1>.算數除零異常案例
package main import ( "fmt" ) func main() { //定義除數 a := 20 //定義被除數 b := 0 //除數不能為0,編譯時並不會報錯,但是在代碼運行時會報錯喲~ c := a / b //由於上面的代碼執行報錯啦,該行代碼不會被執行 fmt.Printf(" %d ➗ %d = %d\n", a, b, c) }
2>.數組索引越界異常案例
package main import ( "fmt" ) func myArr(index int) { //定義數組 var arr [10]int //數組這里賦值時可能會存在一個風險,即索引越界異常 arr[index] = 123 fmt.Println(arr) } func main() { myArr(12) }
二.Go語言中自定義異常接口
1>.使用errors自定義異常消息(並不會使得程序崩潰)
package main import ( "errors" "fmt" ) func div(x int, y int) (res int, err error) { if y == 0 { /* Go語言引入了一個關於錯誤處理的標准模式,即error接口,該接口需要導入"errors"包: errors接口適合返回可控的錯誤,即我們知道在某個代碼塊中可能會出現的異常。 */ err = errors.New("div函數除零異常...") return } res = x / y return } func main() { a := 10 b := 0 /* res: 用來接收運算結果 err: 用來接收錯誤消息 nil: 表示空,"if err != nil"表示變量err接收的錯誤消息是否為空。 */ res, err := div(a, b) if err != nil { fmt.Println(err) //log.Fatal(err) //我們也可以使用log包來幫助咱們輸出錯誤,它會在錯誤消息簽名自動加上日期時間 } else { fmt.Println(res) } fmt.Println("代碼執行完畢") }
2>.使用panic自定義異常消息(程序會崩潰)
package main import ( "fmt" ) func myArr2(index int) { //定義數組 var arr [10]int if index >= 10 { /* panic函數與errors接口不同: (1)使用panic時無需導入包; (2)若出現異常,使用panic封裝異常消息時,會直接導致程序運行結束,換句話說,error是一般性錯誤,而panic函數返回的是讓程序崩潰的錯誤 溫馨提示: 一般而言,當panic異常發生時,程序會中斷運行。隨后,程序崩潰並輸出日志消息。日志信息包括panic value和函數調用的堆棧跟蹤信息 當然,如果直接調用內置的panic函數也會引發panic異常,panic函數接收任何值作為參數。 */ panic("請注意,index > 10,出現了索引越界異常...(index的取值范圍0~9)") } //上面使用了panic接口封裝了異常處理錯誤,因此如果代碼到這一行說明沒有索引越界異常 arr[index] = 123 fmt.Println(arr) } func main() { myArr2(12) fmt.Println("代碼執行完畢") }
三.使用recover進行異常捕獲
1>.defer延遲調用
package main import ( "fmt" ) func main() { /* defer語句被用於預定對一個函數的調用。可以把這類被defer語句調用的函數稱為函數。 defer的應用場景: (1)釋放占用的資源; (2)捕獲異常處理 (3)輸出日志 溫馨提示: 如果一個函數中有多個defer語句,它們會以LIFO(后進先出)的順序執行。 先不要運行代碼,你先猜猜下面的代碼的執行順序。 */ defer fmt.Println("\thttps://www.cnblogs.com/yinzhengjie/") fmt.Println("我的名字叫尹正傑,英文名叫'Jason Yin'.愛好開源技術.") defer fmt.Println("\thttps://www.cnblogs.com/yinzhengjie2020") fmt.Println("我的博客是:") }
2>.defer結合recover進行錯誤攔截
package main import "fmt" func test3(index int) { /* 錯誤攔截要在產生錯誤前設置,因此建議大家把錯誤攔截的函數放在函數內部的首行定義。 */ defer func() { /* 運行時panic異常一旦被引發就會導致程序崩潰 Go語言提供了專用於"攔截"運行時panic的內建函數"recover"。 它可以使當前的程序從運行時panic的狀態中恢復並重新獲得流程控制權,歡聚話說,通過recover進行不可控的錯誤攔截,重新獲取程序的控制權 */ err := recover() if err != nil { fmt.Println(err) } }() /* 定義容量為10的數組 */ var arr [10]int if index >= 10 { panic("請注意,index > 10,出現了索引越界異常...(index的取值范圍0~9)") } arr[index] = 123 fmt.Println(arr) } func main() { test3(5) test3(12) fmt.Println("代碼執行完畢") }
3>.面試題(請根據下面代碼手寫出輸出結果)
package main import ( "fmt" ) func f1() (int, error) { defer fmt.Println(1) defer fmt.Println(2) fmt.Println(3) return fmt.Println(4) } func f2() (int, error) { defer fmt.Println(5) defer fmt.Println(6) fmt.Println(7) f1() defer func() (int, error) { defer fmt.Println(8) fmt.Println(9) return fmt.Println(10) }() return fmt.Println(11) } func main() { f2() }