github.com/haraldrudell/parl@v0.4.176/perrors/errorglue/error-list.go (about) 1 /* 2 © 2021–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package errorglue 7 8 import ( 9 "errors" 10 11 "golang.org/x/exp/slices" 12 ) 13 14 // ErrorList returns the list of associated errors enclosed in all error chains of err 15 // - the returned slice is a list of error chains beginning with the initial err 16 // - If err is nil, a nil slice is returned 17 // - duplicate error values are ignored 18 // - order is: 19 // - — associated errors from err’s error chain, oldest first 20 // - — then associated errors from other error chains, oldest found error of each chain first, 21 // and errors from the last found error chain first 22 // - — 23 // - associated errors are independent error chains that allows a single error 24 // to enclose addditional errors not part of its error chain 25 // - cyclic error values are filtered out so that no error instance is returned more than once 26 func ErrorList(err error) (errs []error) { 27 if err == nil { 28 return // nil error return: nil slice 29 } 30 // errMap ensures that no error instance occurs more than once 31 var errMap = map[error]bool{err: true} 32 33 // process all error chains referred by err and its associated errors 34 // - begin with err 35 for errorChains := []error{err}; len(errorChains) > 0; errorChains = errorChains[1:] { 36 // traverse error chain 37 for errorChain := errorChains[0]; errorChain != nil; errorChain = errors.Unwrap(errorChain) { 38 39 // find any associated error not found before 40 if relatedError, ok := errorChain.(RelatedError); ok { 41 if associatedError := relatedError.AssociatedError(); associatedError != nil { 42 if _, ok := errMap[associatedError]; !ok { 43 44 // store associated error, newest first 45 errs = append(errs, associatedError) 46 // store the error chain for scanning, first found first 47 errorChains = append(errorChains, associatedError) 48 // store associateed error to ensure uniqueness 49 errMap[associatedError] = true 50 } 51 } 52 } 53 } 54 } 55 56 // errs begins with err, then associated errors, oldest first 57 errs = append(errs, err) 58 slices.Reverse(errs) 59 60 return 61 }