错误在go中是一个接口类型,便于自定义错误扩展。
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
Error() string
}
标准库创建错误变量的方式有两种,
第一种是func New(text string) error;
第二种是func Errorf(format string, a …interface{}) error ;
func main() {
err := errors.New("my error")
err1 := fmt.Errorf("my error2")
fmt.Printf("%#v\n", err)
fmt.Printf("%#v\n", err1)
}
/**
output:
&errors.errorString{s:"my error"}
&errors.errorString{s:"my error2"}
*/
以上例子分别使用两种方式创建错误。
var err = errors.New("my error")
var err1 = fmt.Errorf("my error")
func divide1(a, b int)(int, error) {
if b == 0 {
return 0, err
}
return a/b, nil
}
func divide2(a, b int)(int, error) {
if b == 0 {
return 0, err1
}
return a/b, nil
}
func main() {
result2, err2 := divide1(1, 0)
fmt.Println(result2, err2)
result3, err3 := divide2(1, 0)
fmt.Println(result3, err3)
fmt.Println(err2 == err3)
fmt.Printf("%p %#v\n", &err2, err2)
fmt.Printf("%p %#v\n", &err3, err3)
}
/**
ouput:
0 my error
0 my error
false
0xc00005a200 &errors.errorString{s:"my error"}
0xc00005a210 &errors.errorString{s:"my error"}
*/
以上例子可以看出errors提供的创建的错误是很简单的一种错误,只保留了错误信息。需要注意的是使用errors创建错误不支持错误判等。说白了errors只是一种简单的字符串error对象。
前面提到错误是接口,errors提供的错误创建是基于最简单的字符来构建。下面我们可以手工构建一自己的错误类型。
/**
该例子来自《go语言学习笔记》
*/
/**
构建一个错误类型
*/
type DivError struct {
a, b int
}
/**
实现错误接口
*/
func (e DivError) Error() string {
errStr := fmt.Sprintf("Divison by Zero!")
return errStr
}
func div(a, b int) (int, error) {
if b == 0 {
return 0, DivError{a, b}
}
return a / b, nil
}
func main() {
//引发错误
d, err := div(10, 0)
if err != nil {
//错误匹配
switch e := err.(type) {
//优先匹配自定义错误
case DivError:
fmt.Println(e, e.a, e.b)
default:
fmt.Println(e)
}
log.Fatal(err)
}
fmt.Println(d)
}
/**
ouput:
0 Divison by Zero!
Divison by Zero! 10 0
2020/06/01 21:23:22 Divison by Zero!
*/
自定义错误通常以Error为名称后缀,同时当使用swtich进行类型匹配的时候,自定义的错误写在前面,保证优先匹配到具体的错误类型。