github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/lib/errors/errors.go (about) 1 package errors 2 3 import ( 4 "errors" 5 "fmt" 6 "reflect" 7 ) 8 9 // New returns an error that formats as the given text. 10 func New(text string) error { 11 return errors.New(text) 12 } 13 14 // Errorf formats according to a format specifier and returns the string 15 // as a value that satisfies error. 16 func Errorf(format string, a ...interface{}) error { 17 return fmt.Errorf(format, a...) 18 } 19 20 // WalkFunc is the signature of the Walk callback function. The function gets the 21 // current error in the chain and should return true if the chain processing 22 // should be aborted. 23 type WalkFunc func(error) bool 24 25 // Walk invokes the given function for each error in the chain. If the 26 // provided functions returns true or no further cause can be found, the process 27 // is stopped and no further calls will be made. 28 // 29 // The next error in the chain is determined by the following rules: 30 // - If the current error has a `Cause() error` method (github.com/pkg/errors), 31 // the return value of this method is used. 32 // - If the current error has a `Unwrap() error` method (golang.org/x/xerrors), 33 // the return value of this method is used. 34 // - Common errors in the Go runtime that contain an Err field will use this value. 35 func Walk(err error, f WalkFunc) { 36 for prev := err; err != nil; prev = err { 37 if f(err) { 38 return 39 } 40 41 switch e := err.(type) { 42 case causer: 43 err = e.Cause() 44 case wrapper: 45 err = e.Unwrap() 46 default: 47 // Unpack any struct or *struct with a field of name Err which satisfies 48 // the error interface. This includes *url.Error, *net.OpError, 49 // *os.SyscallError and many others in the stdlib. 50 errType := reflect.TypeOf(err) 51 errValue := reflect.ValueOf(err) 52 if errValue.IsValid() && errType.Kind() == reflect.Ptr { 53 errType = errType.Elem() 54 errValue = errValue.Elem() 55 } 56 if errValue.IsValid() && errType.Kind() == reflect.Struct { 57 if errField := errValue.FieldByName("Err"); errField.IsValid() { 58 errFieldValue := errField.Interface() 59 if newErr, ok := errFieldValue.(error); ok { 60 err = newErr 61 } 62 } 63 } 64 } 65 if reflect.DeepEqual(err, prev) { 66 break 67 } 68 } 69 } 70 71 type causer interface { 72 Cause() error 73 } 74 type wrapper interface { 75 Unwrap() error 76 }