errors. Is
用于判断该错误是否是某个类型,1.18 后,官方推荐使用 Is 来判断错误是否相等。
package main
import (
"errors"
"fmt"
)
var (
ErrDivideByZero = errors.New("divide by zero")
ErrNegativeSquareRoot = errors.New("square root is negative")
)
func mathFunc(a, b int) error {
if b == 0 {
return ErrDivideByZero
} else {
return nil
}
}
func main() {
var a, b int
err := mathFunc(a, b)
if err != nil {
// 此处等价于 err == ErrDivideByZero
if errors.Is(err, ErrDivideByZero) {
fmt.Println("除数为0异常")
} else if errors.Is(err, ErrNegativeSquareRoot) {
fmt.Println("对于负数开方异常")
}
}
}
和等号判断 err 是否相等相比,Is 判断还有个好处,就是如果是该错误的包装的话,Is 判断依据相等
package main
import (
"errors"
"fmt"
)
var (
ErrDivideByZero = errors.New("divide by zero")
ErrNegativeSquareRoot = errors.New("square root is negative")
)
func mathFunc(a, b int) error {
if b == 0 {
// %w,可以对一个错误进行包装,应该是wrap的缩写
return fmt.Errorf("mathFunc %w", ErrDivideByZero)
} else {
return nil
}
}
func main() {
var a, b int
err := mathFunc(a, b)
if err != nil {
// fmt.Errorf("mathFunc %w", ErrDivideByZero),包装后,是不同的类型,不相等了
if err == ErrDivideByZero {
fmt.Println("除数为0异常,通过等号方式")
}
// 但是这个Is判断依旧相等
if errors.Is(err, ErrDivideByZero) {
fmt.Println("除数为0异常")
} else if errors.Is(err, ErrNegativeSquareRoot) {
fmt.Println("对于负数开方异常")
}
}
}
errors. As
这个方法除了可以判读类型是否是同一种,如果是的话,还会赋值初始化。
package main
import (
"errors"
"fmt"
)
type DivisionError struct {
IntA int
IntB int
Msg string
}
func (e DivisionError) Error() string {
return e.Msg
}
type SquareError struct {
IntA int
IntB int
Msg string
}
func (e SquareError) Error() string {
return e.Msg
}
func mathFunc(a, b int) error {
if b == 0 {
err := DivisionError{IntA: a, IntB: b, Msg: "除数为0"}
return err
} else {
return nil
}
}
func main() {
var a, b int
err := mathFunc(a, b)
var de DivisionError
var se SquareError
if err != nil {
// 判断err是否是DivisionError错误
// 如果是的话,将err初始化到de,所以需要传指针
if errors.As(err, &de) {
// 所以这边可以直接取err的具体信息
fmt.Printf("除数为0异常,a=%d,b=%d,msg=%s\n", de.IntA, de.IntB, de.Msg)
} else if errors.Is(err, &se) {
fmt.Printf("对负数开方异常,a=%d,b=%d,msg=%s\n", de.IntA, de.IntB, de.Msg)
}
}
}
同样,如果对错误进行包装,erros.As
判断依据成立
package main
import (
"errors"
"fmt"
)
type DivisionError struct {
IntA int
IntB int
Msg string
}
func (e DivisionError) Error() string {
return e.Msg
}
type SquareError struct {
IntA int
IntB int
Msg string
}
func (e SquareError) Error() string {
return e.Msg
}
func mathFunc(a, b int) error {
if b == 0 {
err := DivisionError{IntA: a, IntB: b, Msg: "除数为0"}
// 对错误进行包装
return fmt.Errorf("mathFunc %w", err)
} else {
return nil
}
}
func main() {
var a, b int
err := mathFunc(a, b)
var de DivisionError
var se SquareError
if err != nil {
// 判断err是否是DivisionError错误
// 如果是的话,将err初始化到de,所以需要传指针
if errors.As(err, &de) {
// 所以这边可以直接取err的具体信息
fmt.Printf("除数为0异常,a=%d,b=%d,msg=%s\n", de.IntA, de.IntB, de.Msg)
} else if errors.Is(err, &se) {
fmt.Printf("对负数开方异常,a=%d,b=%d,msg=%s\n", de.IntA, de.IntB, de.Msg)
}
}
}