基本的異常處理
目前流行的語言錯誤處理都是透過 try
catch
finally
關鍵字或類關鍵字處理的
但是在 golang
中提供了一些全新模式, 不同於 try
catch
語句, go語言透過函式返回錯誤來捕獲, go內建了error介面, 只要實現Error() string方法, 透過判斷 err
是否是 nil
來捕獲異常.
func div(x float32, y float32) (result float32, err error) {}
golang
中提供了 defer
關鍵字, 這個語句會在執行完當前函式後執行, 類似 finally
func main() {
// 相當於finally
defer println("done!")
println("hello, world")
}
舉個具體的例子:
package main
import (
"fmt"
"math"
)
// 宣告零除錯誤
type ZeroDivError struct {
code int
message string
}
// 實現error介面
func (e ZeroDivError) Error() string {
return fmt.Sprintf("%v: %v", e.code, e.message)
}
func div(x float32, y float32) (result float32, err error) {
if y == 0 {
return float32(math.Inf(1)), ZeroDivError{1, "零除問題"}
}
return x / y, err
}
func main() {
// 相當於finally
defer func() {
println("done!")
}
// 這個相當於
// try { r := div(1, 0) } catch e { println(r, e.Error() }
r, e := div(1, 0)
if e != nil {
println(r, e.Error())
}
}
panic 和 recover
golang
還提供了兩個關鍵字 panic
和 recover
, 按照上面的異常處理方式需要把錯誤一層一層的傳遞出去, 這兩個關鍵字主要目的是用來做跨層級的異常捕獲.
panic
用來立馬中斷當前程式返回異常, recover
用來捕獲 panic
異常程式會繼續執行
recover
只能在 defer
中才可以生效
panic
可以多次執行, 呼叫 recover
時會按順序捕獲錯誤
package main
import "fmt"
func a() {
defer func() {
e := recover()
fmt.Printf("a e: %v\n", e)
println("a done!")
}()
panic("a fatal!")
}
func b() {
defer func() {
e := recover()
fmt.Printf("b e: %v\n", e)
println("b done!")
}()
panic("b fatal!")
}
func main() {
defer func() {
e := recover()
fmt.Printf("main e: %v\n", e)
println("main done!")
}()
a()
b()
panic("main fatal!")
}
執行結果
a e: a fatal!
a done!
b e: b fatal!
b done!
main e: main fatal!
main done!