Go通關07:錯誤處理,如何通過error/panic處理錯誤?
阿新 • • 發佈:2021-08-07
錯誤
在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 關鍵字修飾的函式,會在主函式退出前被執行。