github.com/haraldrudell/parl@v0.4.176/perrors/publics.go (about) 1 /* 2 © 2021–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package perrors 7 8 import ( 9 "strings" 10 11 "github.com/haraldrudell/parl/perrors/errorglue" 12 "github.com/haraldrudell/parl/pruntime" 13 ) 14 15 // error116.Warning indicates that err is a problem of less severity than error. 16 // It is uesed for errors that are not to terminate the thread. 17 // A Warning can be detected using error116.IsWarning(). 18 func Warning(err error) error { 19 return Stack(errorglue.NewWarning(err)) 20 } 21 22 // error116.AddKeyValue attaches a string value to err. 23 // The values can be trrioeved using error116.ErrorData(). 24 // if key is non-empty valiue is returned in a map where last key wins. 25 // if key is empty, valuse is returned in s string slice. 26 // err can be nil. 27 func AddKeyValue(err error, key, value string) (e error) { 28 return errorglue.NewErrorData(err, key, value) 29 } 30 31 // AppendError associates an additional error with err. 32 // - return value is nil if and only if both err and err2 are nil 33 // - if either err or err2 is nil, return value is the non-nil argument 34 // - if both err and err2 are non-nil, the return value is err with err2 associated 35 // - associated error instances can be retrieved using: 36 // - — perrors.AllErrors, 37 // - — perros.ErrorList or 38 // - — by rich error printing of perrors package: perrors.Long or 39 // - — “%+v” 40 func AppendError(err error, err2 error) (e error) { 41 if err2 == nil { 42 e = err // err2 is nil, return is err, possibly nil 43 } else if err == nil { 44 e = err2 // err is nil, return is non-nil err2 45 } else { 46 e = errorglue.NewRelatedError(err, err2) // both non-nil 47 } 48 return 49 } 50 51 // AppendErrorDefer aggregates error sources into errp. 52 // - AppendErrorDefer is deferrable 53 // - errp cannot be nil 54 // - errp2 is a pointer to a second error variable used as source. 55 // If errp2 is nil or *errp2 is nil, no action is taken 56 // - fn is a function returning a possible error. 57 // If fn is nil or fn returns nil, no action is taken 58 // - AppendErrorDefer uses AppendError to aggregate error values into *errp 59 func AppendErrorDefer(errp, errp2 *error, fn func() (err error)) { 60 if errp == nil { 61 panic(NewPF("errp cannot be nil")) 62 } 63 if errp2 != nil { 64 if err := *errp2; err != nil { 65 *errp = AppendError(*errp, err) 66 } 67 } 68 if fn != nil { 69 if err := fn(); err != nil { 70 *errp = AppendError(*errp, err) 71 } 72 } 73 } 74 75 func TagErr(e error, tags ...string) (err error) { 76 var frames = 1 // count TagErr frame 77 78 // ensure error has stack 79 if !HasStack(e) { 80 e = Stackn(e, frames) 81 } 82 83 // values to print 84 s := pruntime.NewCodeLocation(frames).PackFunc() 85 if tagString := strings.Join(tags, "\x20"); tagString != "" { 86 s += "\x20" + tagString 87 } 88 89 return Errorf("%s: %w", s, e) 90 } 91 92 // InvokeIfError invokes errFn with *errp if *errp is non-nil 93 // - used as a deferred conditional error storer 94 // - deferrable, thread-safe 95 // 96 // Usage: 97 // 98 // func someFunc() { 99 // var err error 100 // defer perrors.InvokeIfError(&err, addError) 101 func InvokeIfError(errp *error, errFn func(err error)) { 102 var err error 103 if errp != nil { 104 err = *errp 105 } else { 106 err = New("perrors.InvokeIfError errp nil") 107 } 108 if err != nil { 109 errFn(err) 110 } 111 }