兄弟連go教程(15)函式 - 錯誤處理

尹成發表於2018-07-04
沒有結構化異常,使⽤用 panic 丟擲錯誤,recover 捕獲錯誤。
func test() {

defer func() {
if err := recover(); err != nil {
println(err.(string)) // 將 interface{} 轉型為具體型別。
}
}()
panic("panic error!")
}


由於 panic、recover 引數型別為 interface{},因此可丟擲任何型別物件。
func panic(v interface{})
func recover() interface{}


延遲調⽤用中引發的錯誤,可被後續延遲調⽤用捕獲,但僅最後⼀一個錯誤可被捕獲。
func test() {
defer func() {
fmt.Println(recover())
}()
defer func() {
panic("defer panic")
}()
panic("test panic")
}
func main() {
test()
}


輸出:
defer panic
捕獲函式 recover 只有在延遲調⽤用內直接調⽤用才會終⽌止錯誤,否則總是返回 nil。任何未
捕獲的錯誤都會沿調⽤用堆疊向外傳遞。
func test() {
defer recover() // ⽆無效!
defer fmt.Println(recover()) // ⽆無效!
defer func() {
func() {
println("defer inner")
recover() // ⽆無效!
}()

}()
panic("test panic")
}
func main() {
test()
}


輸出:
defer inner
<nil>
panic: test panic


使⽤用延遲匿名函式或下⾯面這樣都是有效的。
func except() {
recover()
}
func test() {
defer except()
panic("test panic")
}


如果需要保護程式碼⽚片段,可將程式碼塊重構成匿名函式,如此可確保後續程式碼被執⾏行。
func test(x, y int) {
var z int
func() {
defer func() {
if recover() != nil { z = 0 }
}()
z = x / y
return
}()
println("x / y =", z)
}


除⽤用 panic 引發中斷性錯誤外,還可返回 error 型別錯誤物件來表⽰示函式調⽤用狀態。
type error interface {
Error() string

}


標準庫 errors.New 和 fmt.Errorf 函式⽤用於建立實現 error 接⼝口的錯誤物件。通過判斷
錯誤物件例項來確定具體錯誤型別。
var ErrDivByZero = errors.New("division by zero")
func div(x, y int) (int, error) {
if y == 0 { return 0, ErrDivByZero }
return x / y, nil
}
func main() {
switch z, err := div(10, 0); err {
case nil:
println(z)
case ErrDivByZero:
panic(err)
}
}


如何區別使⽤用 panic 和 error 兩種⽅方式?慣例是:導致關鍵流程出現不可修復性錯誤的

使⽤用 panic,其他使⽤用 error。



尹成老師

QQ77025077 

微信18510341407

所有視訊在尹成學院

www.yinchengxueyuan.com

尹成百度雲請聯絡QQ475318423




相關文章