您好,登錄后才能下訂單哦!
這篇文章主要介紹了Go語言的錯誤處理方式是什么的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Go語言的錯誤處理方式是什么文章都會有所收獲,下面我們一起來看看吧。
在 go 語言中,有一個預定義的接口:error,該接口自帶一個 Error() 方法,調用該方法會返回一個字符串。
type error interface { Error() string }
調用該方法,會返回當前錯誤的具體結果。一般有下面幾種方式生成 error。
errors.New()
fmt.Errorf()
調用 errors.New() 會返回一個 error 類型的結構體,該結構體內部會實現一個 Error() 方法, 調用該方法返回的結果為調用 errors.New() 方法時傳入的內容。
import ( "errors" "fmt" ) func divide(a, b int) (error, int) { if b == 0 { // 被除數為0,則構造一個 error 結構體 return errors.New("被除數不能為0"), 0 } var result = a / b return nil, result } func main() { var err error // error 類型數據的初始值為 nil,類似于 js 中的 null var result int err, result = divide(1, 0) if err == nil { // 如果 err 為 nil,說明運行正常 fmt.Println("計算結果", result) } else { // 如果 err 不為 nil,說明運行出錯 // 調用 error 結構體的 Error 方法,輸出錯誤原因 fmt.Println("計算出錯", err.Error()) } }
可以看到,上面的代碼中,由于調用 divide 除法方法時,由于傳入的被除數為 0。經過判斷,會拋出一個由 errors.New 構造的 error 類型的結構體。
我們將調用 error.Error() 方法返回的結果輸出到控制臺,可以發現其返回的結果,就是傳入 New 方法的值。
執行結果如下:
通過 fmt.Errorf() 方法構造的 error 結構體,與調用 errors.New() 方法的結果類似。不同的是,fmt.Errorf() 方法會進行一次數據的格式化。
func divide(a, b int) (error, int) { if b == 0 { // 將參數進行一次格式化,格式化后的字符串放入 error 中 return fmt.Errorf("數據 %d 不合法", b), 0 } var result = a / b return nil, result } err, result := divide(1, 0) fmt.Println("計算出錯", err.Error())
執行結果如下:
panic()
panic() 相當于主動停止程序運行,調用時 panic() 時,需要傳入中斷原因。調用后,會在控制臺輸出中斷原因,以及中斷時的調用堆棧。我們可以改造一下之前的代碼:
func divide(a, b int) (error, int) { if b == 0 { // 如果程序出錯,直接停止運行 panic("被除數不能為0") } var result = a / b return nil, result } func main() { err, result := divide(1, 0) fmt.Println("計算出錯", err.Error()) }
在運行到 panic() 處,程序直接中斷,并在控制臺打印出了中斷原因。
panic() 可以理解為,js 程序中的 throw new Error() 的操作。那么,在 go 中有沒有辦法終止 panic() ,也就是類似于 try-catch 的操作,讓程序回到正常的運行邏輯中呢?
在介紹 recover() 方法之前,還需要介紹一個 go 語言中的另一個關鍵字:defer。
defer 后的語句會在函數進行 return 操作之前調用,常用于資源釋放、錯誤捕獲、日志輸出。
func getData(table, sql) { defer 中斷連接() db := 建立連接(table) data := db.select(sql) return data }
defer 后的語句會被存儲在一個類似于棧的數據結構內,在函數結束的時候,被定義的語句按順序出棧,越后面定義的語句越先被調用。
func divide(a, b int) int { defer fmt.Println("除數為", b) defer fmt.Println("被除數為", a) result := a / b fmt.Println("計算結果為", result) return result } divide(10, 2)
上面的代碼中,我們在函數開始運行的時候,先通過 defer 定義了兩個輸出語句,先輸出除數,后輸出被除數。
實際的運行結果是:
先輸出計算結果;
然后輸出被除數;
最后輸出除數;
這和前面提到的,通過 defer 定義的語句會在函數結束的時候,按照出棧的方式進行執行,先定義的后執行。defer 除了會在函數結束的時候執行,出現異常的的時候也會先走 defer 的邏輯,也就是說,我們在調用了 panic() 方法后,程序中斷過程中,也會先將 defer 內的語句運行一遍。
這里我們重新定義之前的 divide 函數,在執行之前加上一個 defer 語句,defer 后面為一個自執行函數,該函數內會調用 recover() 方法。
recover() 方法調用后,會捕獲到當前的 panic() 拋出的異常,并進行返回,如果沒有異常,則返回 nil。
func divide(a, b int) int { // 中斷之前,調用 defer 后定義的語句 defer func() { if err := recover(); err != nil { fmt.Println("捕獲錯誤", err) } }() if b == 0 { // 函數運行被中斷 panic("被除數不能為0") return 0 } return a / b } result := divide(1, 0) fmt.Println("計算結果", result)
上面的代碼運行后,我們發現之前調用 panic() 中斷的程序被恢復了,而且后面的計算結果也正常進行輸出了。
這就有點類似于 try-catch 的邏輯了,只是 recover 需要放在 defer 關鍵詞后的語句中,更像是 catch 和 finally 的結合。
關于“Go語言的錯誤處理方式是什么”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Go語言的錯誤處理方式是什么”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。