github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zerror/error.go (about) 1 package zerror 2 3 import ( 4 "errors" 5 6 "github.com/sohaha/zlsgo/zutil" 7 ) 8 9 type ( 10 // ErrCode error code type 11 ErrCode int32 12 // Error wraps err with code 13 Error struct { 14 err error 15 wrapErr error 16 errText *string 17 stack zutil.Stack 18 code ErrCode 19 inner bool 20 } 21 22 External func(err error) error 23 ) 24 25 var ( 26 goROOT = zutil.GOROOT() 27 ) 28 29 func New(code ErrCode, text string, w ...External) error { 30 var err error = &Error{ 31 code: code, 32 stack: zutil.Callers(3), 33 errText: &(&[1]string{text})[0], 34 } 35 36 for i := range w { 37 err = w[i](err) 38 } 39 40 return err 41 } 42 43 // Reuse the error 44 func Reuse(err error) error { 45 if err == nil { 46 return nil 47 } 48 if e, ok := err.(*Error); ok { 49 return e 50 } 51 return &Error{ 52 err: err, 53 stack: zutil.Callers(3), 54 } 55 } 56 57 // Wrap wraps err with code 58 func Wrap(err error, code ErrCode, text string, w ...External) error { 59 if err == nil { 60 return nil 61 } 62 63 for i := range w { 64 err = w[i](err) 65 } 66 67 return &Error{ 68 wrapErr: err, 69 code: code, 70 stack: zutil.Callers(3), 71 errText: &(&[1]string{text})[0], 72 } 73 } 74 75 // Deprecated: please use zerror.With 76 // SupText returns the error text 77 func SupText(err error, text string) error { 78 return With(err, text) 79 } 80 81 // With returns the inner error's text 82 func With(err error, text string, w ...External) error { 83 if err == nil { 84 return &Error{ 85 stack: zutil.Callers(3), 86 errText: &(&[1]string{text})[0], 87 } 88 } 89 90 for i := range w { 91 err = w[i](err) 92 } 93 94 return &Error{ 95 wrapErr: err, 96 inner: true, 97 stack: zutil.Callers(3), 98 errText: &(&[1]string{text})[0], 99 } 100 } 101 102 // Unwrap returns if err is Error and its code == code 103 func Unwrap(err error, code ErrCode) (error, bool) { 104 for { 105 if err == nil { 106 return nil, false 107 } 108 109 e, ok := err.(*Error) 110 if !ok { 111 return err, false 112 } 113 114 if e.code == code { 115 if e.errText != nil { 116 return errors.New(*e.errText), true 117 } 118 119 return e.err, true 120 } 121 122 err = e.Unwrap() 123 } 124 } 125 126 // Is returns if err is Error and its code == code 127 func Is(err error, code ...ErrCode) bool { 128 for i := range code { 129 _, ok := Unwrap(err, code[i]) 130 if ok { 131 return true 132 } 133 } 134 135 return false 136 } 137 138 // UnwrapCode Returns the current error code 139 func UnwrapCode(err error) (ErrCode, bool) { 140 if err == nil { 141 return 0, false 142 } 143 144 e, ok := err.(*Error) 145 if !ok { 146 return 0, false 147 } 148 149 if e.code == 0 { 150 return UnwrapCode(e.wrapErr) 151 } 152 153 return e.code, true 154 } 155 156 // UnwrapCodes Returns the current all error code 157 func UnwrapCodes(err error) (codes []ErrCode) { 158 for { 159 if err == nil { 160 return 161 } 162 163 e, ok := err.(*Error) 164 if !ok { 165 return 166 } 167 168 codes = append(codes, e.code) 169 170 err = e.Unwrap() 171 } 172 } 173 174 // UnwrapErrors Returns the current all error text 175 func UnwrapErrors(err error) (errs []string) { 176 for { 177 if err == nil { 178 return 179 } 180 181 e, ok := err.(*Error) 182 if !ok { 183 errs = append(errs, err.Error()) 184 return 185 } 186 187 if e.errText != nil { 188 errs = append(errs, *e.errText) 189 } else { 190 errs = append(errs, e.err.Error()) 191 } 192 193 err = e.Unwrap() 194 } 195 } 196 197 func UnwrapFirst(err error) (ferr error) { 198 for { 199 if err == nil { 200 return 201 } 202 203 e, ok := err.(*Error) 204 if !ok { 205 return err 206 } 207 208 if e.errText != nil { 209 ferr = errors.New(*e.errText) 210 } else { 211 ferr = e.err 212 } 213 214 err = e.Unwrap() 215 } 216 } 217 218 func UnwrapFirstCode(err error) (code ErrCode) { 219 for { 220 if err == nil { 221 return 222 } 223 224 e, ok := err.(*Error) 225 if !ok { 226 return 227 } 228 229 code = e.code 230 231 err = e.Unwrap() 232 } 233 }