1、Go error本質上是什麼?
type error interface {
Error() string
}
說白了,error實際上是一個接口,接口裏面就一個方法:Error() string
2、如何自定義錯誤類型
2.1 既然是接口,那就定義一個實現類
package main
import (
"fmt"
"reflect"
)
type MyErr1 struct {
}
func (this *MyErr1) Error() string {
return "this is MyErr1"
}
func main() {
var err error = nil
err = &MyErr1{}
fmt.Println(reflect.TypeOf(err))
fmt.Println("type err1-->", err)
}
*main.MyErr1
type err1--> this is MyErr1
2.2 也可以藉助fmt,快速創建一個錯誤值
package main
import (
"fmt"
"reflect"
)
func main() {
err := fmt.Errorf("this is MyErr2")
fmt.Println(reflect.TypeOf(err))
fmt.Println("type err2-->", err)
}
*errors.errorString
type err2--> this is MyErr2
2.3 還可以藉助errors包
package main
import (
"errors"
"fmt"
"reflect"
)
func main() {
err := errors.New("this is MyErr3")
fmt.Println(reflect.TypeOf(err))
fmt.Println("type err3-->", err)
}
*errors.errorString
type err3--> this is MyErr3
可以看到系統快速創建的error都是*errors.errorString類型的
3、如何判斷錯誤類型
一個方法可能返回多種錯誤類型,調用方常常需要根據不同類型的錯誤做出不同的處理。區分錯誤類型是非常常見和重要的。
我們以*errors.errorString來看看如何區分錯誤類型,常見的做法是這樣子的
package main
import (
"errors"
"fmt"
)
var err_1 = errors.New("this is err type 1")
var err_2 = errors.New("this is err type 2")
func main() {
j, err := tryErr(-10)
if err == err_1 {
fmt.Println(err)
return
}
if err == err_2 {
fmt.Println(err)
return
}
fmt.Println("success", j)
}
func tryErr(i int) (int, error) {
if i < 0 {
return -1, err_1
} else if i == 0 {
return -1, err_2
} else {
return i, nil
}
}
可以看到這種“常見做法”裏面,錯誤是作爲一個值來判斷的。這種方式與Java裏面的異常機制又很大區別
try{
...
}
catch(Exception1 e1){
...
}
catch(Exception2 e2){
...
}
這個是java裏面的異常機制,可以看到catch是按照類型來匹配的。
這兩種機制孰優孰劣呢?很明顯,以值來判斷錯誤類型只能攜帶錯誤類型本身的類型信息。不能反映出錯誤的更多細節。
4、Go裏面以錯誤值的類型判斷錯誤類型——使用類型斷言
package main
import (
"fmt"
"strconv"
)
type MyErr1 struct {
err_mag string //錯誤消息信息
}
func (this *MyErr1) Error() string {
return this.err_mag
}
type MyErr2 struct {
err_mag string //錯誤消息信息
}
func (this *MyErr2) Error() string {
return this.err_mag
}
func main() {
j, err := tryErr(-10)
switch err.(type) {
case *MyErr1:
fmt.Println(err)
return
case *MyErr2:
fmt.Println(err)
return
default:
fmt.Println("success", j)
}
}
func tryErr(i int) (int, error) {
if i < 0 {
return -1, &MyErr1{"error message 1-->" + strconv.Itoa(i)}
} else if i == 0 {
return -1, &MyErr2{"error message 2-->" + strconv.Itoa(i)}
} else {
return i, nil
}
}