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