1.why shoud we wrap go error
var ErrPermission = errors.New("permission denied")
// DoSomething returns an error wrapping ErrPermission if the user
// does not have permission to do something.
func DoSomething() {
if !userHasPermission() {
// If we return ErrPermission directly, callers might come
// to depend on the exact error value, writing code like this:
//
// if err := pkg.DoSomething(); err == pkg.ErrPermission { … }
//
// This will cause problems if we want to add additional
// context to the error in the future. To avoid this, we
// return an error wrapping the sentinel so that users must
// always unwrap it:
//
// if err := pkg.DoSomething(); errors.Is(err, pkg.ErrPermission) { ... }
return fmt.Errorf("%w", ErrPermission)
}
// ...
}
2.usage
var brokenErr = errors.New("I'am broken!")
// ...
err4 := fmt.Errorf("some %v wrong: %w", "james", brokenErr)
fmt.Println(err4.Error())
fmt.Println(errors.Unwrap(err4).Error())
// value equal
fmt.Println("is: ", errors.Is(err4, brokenErr))
// type assert, second param must pointer or interface. use &.
fmt.Println("as: ", errors.As(err4, &brokenErr))
3.details
- errors.Is will recursive all errors wraped in the error, if any one is equal then return true.
- errors.As also recursive the errors wraped, if find the first type match then return true, else return nil.
- we use [Is] to check if the internal error is some thing.
- we use [As] to handle all the specific type errors.
网友评论