1. 程式人生 > 其它 >Go通關07:錯誤處理,如何通過error/panic處理錯誤?

Go通關07:錯誤處理,如何通過error/panic處理錯誤?

錯誤

在Go語言中,錯誤並不是非常嚴重,它是可以預期的,可以返回錯誤給呼叫者自行處理。

error 介面

在Go語言中,錯誤是通過內建的error介面來表示的,它只有一個Error方法來返回錯誤資訊:

type error interface {
  Error() string
}

這裡演示一個錯誤的示例:

func main() {
   i,err := strconv.Atoi("a")
   if err != nil {
      fmt.Println(err)
   }else {
      fmt.Println(i)
   }
}
  • 示例故意使用錯誤的字串“a”來轉為整數,所以這裡會列印錯誤資訊:
    strconv.Atoi: parsing "a": invalid syntax
  • 一般,error介面在當函式或方法呼叫時遇到錯誤時進行返回,且為第二個返回值,這樣呼叫者就可以根據錯誤來自行處理。

error 工廠函式

我們可以使用 errors.New 這個工廠函式來生成錯誤資訊,它接收一個字串引數,返回一個error介面。

func test(m,n int) (int, error) {
  if m > n {
    return m,errors.New("m大於n")
  }else {
    return n,nil
  }
}

當m大約n的情況下,返回一個錯誤資訊。

自定義 error

上面工廠函式只能傳遞一個字串來返回,要想攜帶更多資訊,這時候可以使用自定義error:

type testError struct {
   errorCode int //錯誤碼
   errorMsg string //錯誤資訊
}
func (t *testError) Error() string{
   return t.errorMsg
}

這裡自定義error,它可以返回更多資訊:

return m, &testError{
   errorCode: 1,
   errorMsg:  "m大於n"}

上面通過字面量方式建立*testError 來返回。

error 斷言

通過error斷言來獲取返回的錯誤資訊,斷言可以將error介面轉為自己定義的錯誤型別:

res, err := test(2,1)
if e,ok := err.(*testError);ok {
  fmt.Println("錯誤碼:",e.errorCode,",錯誤資訊:",e.errorMsg)
} else {
  fmt.Println(res)
}

Panic 異常

Go語言是一門靜態語言,很多錯誤可以在編譯的時候進行捕獲,不過對於陣列越界訪問、不同型別強制轉換這種,會在執行時候才會引起panic異常。
我們也可以手動來丟擲 panic 異常,這裡以連線mysql資料庫為例:

func connectMySQL(ip,username,password string){
   if ip =="" {
      panic("ip不能為空")
   }
   //省略其他程式碼
}
  • 在以上函式中,如果ip地址為空,會丟擲 panic 異常。
  • panic 是Go語言內建函式,可以接收 interface{} 型別的引數,也就是說任何型別的值都是可以傳遞給 panic 函式的:
func panic(v interface{})

interface{} 表示空介面,代表任意型別。
panic 是一種非常嚴重的錯誤,會使程式中斷執行,所以 如果不是影響程式執行的錯誤,使用 error 即可

Recover 捕獲 Panic 異常

一般我們不對panic異常做處理,但是如果有一些需要在程式崩潰前做處理的操作,可以使用內建的 recover 函式來恢復 panic 異常。
程式 panic 異常崩潰的時候,只有defer修飾的函式才會被執行,所以 recover 函式要結合 defer 關鍵字一起使用:

func main() {
   defer func() {
      if p:=recover();p!=nil{
         fmt.Println(p)
      }
   }()
   connectMySQL("","root","123456")
}

recover 函式捕獲了 panic 異常,列印:recover 函式返回的值就是通過 panic 函式傳遞的引數值。 ip不能為空

  • recover 函式的返回值就是 panic 函式傳遞的引數值。
  • defer 關鍵字修飾的函式,會在主函式退出前被執行。