github.com/wangyougui/gf/v2@v2.6.5/errors/gerror/gerror_error.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 7 package gerror 8 9 import ( 10 "errors" 11 "fmt" 12 "runtime" 13 "strings" 14 15 "github.com/wangyougui/gf/v2/errors/gcode" 16 ) 17 18 // Error is custom error for additional features. 19 type Error struct { 20 error error // Wrapped error. 21 stack stack // Stack array, which records the stack information when this error is created or wrapped. 22 text string // Custom Error text when Error is created, might be empty when its code is not nil. 23 code gcode.Code // Error code if necessary. 24 } 25 26 const ( 27 // Filtering key for current error module paths. 28 stackFilterKeyLocal = "/errors/gerror/gerror" 29 ) 30 31 var ( 32 // goRootForFilter is used for stack filtering in development environment purpose. 33 goRootForFilter = runtime.GOROOT() 34 ) 35 36 func init() { 37 if goRootForFilter != "" { 38 goRootForFilter = strings.ReplaceAll(goRootForFilter, "\\", "/") 39 } 40 } 41 42 // Error implements the interface of Error, it returns all the error as string. 43 func (err *Error) Error() string { 44 if err == nil { 45 return "" 46 } 47 errStr := err.text 48 if errStr == "" && err.code != nil { 49 errStr = err.code.Message() 50 } 51 if err.error != nil { 52 if errStr != "" { 53 errStr += ": " 54 } 55 errStr += err.error.Error() 56 } 57 return errStr 58 } 59 60 // Cause returns the root cause error. 61 func (err *Error) Cause() error { 62 if err == nil { 63 return nil 64 } 65 loop := err 66 for loop != nil { 67 if loop.error != nil { 68 if e, ok := loop.error.(*Error); ok { 69 // Internal Error struct. 70 loop = e 71 } else if e, ok := loop.error.(ICause); ok { 72 // Other Error that implements ApiCause interface. 73 return e.Cause() 74 } else { 75 return loop.error 76 } 77 } else { 78 // return loop 79 // 80 // To be compatible with Case of https://github.com/pkg/errors. 81 return errors.New(loop.text) 82 } 83 } 84 return nil 85 } 86 87 // Current creates and returns the current level error. 88 // It returns nil if current level error is nil. 89 func (err *Error) Current() error { 90 if err == nil { 91 return nil 92 } 93 return &Error{ 94 error: nil, 95 stack: err.stack, 96 text: err.text, 97 code: err.code, 98 } 99 } 100 101 // Unwrap is alias of function `Next`. 102 // It is just for implements for stdlib errors.Unwrap from Go version 1.17. 103 func (err *Error) Unwrap() error { 104 if err == nil { 105 return nil 106 } 107 return err.error 108 } 109 110 // Equal reports whether current error `err` equals to error `target`. 111 // Please note that, in default comparison for `Error`, 112 // the errors are considered the same if both the `code` and `text` of them are the same. 113 func (err *Error) Equal(target error) bool { 114 if err == target { 115 return true 116 } 117 // Code should be the same. 118 // Note that if both errors have `nil` code, they are also considered equal. 119 if err.code != Code(target) { 120 return false 121 } 122 // Text should be the same. 123 if err.text != fmt.Sprintf(`%-s`, target) { 124 return false 125 } 126 return true 127 } 128 129 // Is reports whether current error `err` has error `target` in its chaining errors. 130 // It is just for implements for stdlib errors.Is from Go version 1.17. 131 func (err *Error) Is(target error) bool { 132 if Equal(err, target) { 133 return true 134 } 135 nextErr := err.Unwrap() 136 if nextErr == nil { 137 return false 138 } 139 if Equal(nextErr, target) { 140 return true 141 } 142 if e, ok := nextErr.(IIs); ok { 143 return e.Is(target) 144 } 145 return false 146 }