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
}
}