chained errors introduced

This commit is contained in:
2021-09-09 16:35:48 +02:00
parent 99f4cca565
commit 53d843e2e3
5 changed files with 135 additions and 8 deletions

View File

@ -12,14 +12,13 @@ type Error struct {
callTrace *CallTrace
tmpl *ErrTmpl
cause error
prev []error
}
// New returns a new Error with the given message
func New(msg string) *Error {
return &Error{
msg: msg,
cause: nil,
tmpl: nil,
callTrace: Trace(2),
}
}
@ -33,6 +32,16 @@ func Wrap(msg string, cause error) *Error {
}
}
// Chain returns a new Error with the given message and a slice of errors
// which were caused in the same function in succession
func Chain(msg string, errors []error) *Error {
return &Error{
msg: msg,
callTrace: Trace(2),
prev: errors,
}
}
func errtype(err error) string {
if e, ok := err.(*Error); ok && e.tmpl != nil {
return errtype(e.tmpl)
@ -83,8 +92,43 @@ func (e *Error) Is(target error) bool {
return false
}
// Get Returns the first error in the chain for which errors.Is(target) returns true
func (e *Error) Get(target error) error {
if e.prev == nil {
return nil
}
for _, prevErr := range e.prev {
if errors.Is(prevErr, target) {
return prevErr
}
}
return nil
}
// GetByIndex returns the i'th error in the chain
func (e *Error) GetByIndex(i int) error {
if e.prev == nil {
return nil
}
return e.prev[i]
}
// Contains is a shorthand for Get(target) != nil.
// Can be considered as an errors.Is function but for chains instead of causes
func (e *Error) Contains(target error) bool {
return e.Get(target) != nil
}
// Chain returns a slice of all chained errors
func (e *Error) Chain() []error {
return e.prev[:]
}
func printErr(err error, b *strings.Builder) {
if e, ok := err.(*Error); ok {
e, ok := err.(*Error)
if ok {
b.WriteString(errtype(e))
b.WriteString(": ")
b.WriteString(e.msg)
@ -94,7 +138,8 @@ func printErr(err error, b *strings.Builder) {
b.WriteString(errtype(err))
b.WriteString(": ")
b.WriteString(err.Error())
b.WriteString("\n\t(Unknown source)\n")
b.WriteString("\n")
b.WriteString("\t(Unknown source)\n")
}
cause := errors.Unwrap(err)
@ -102,4 +147,11 @@ func printErr(err error, b *strings.Builder) {
b.WriteString("Caused by ")
printErr(cause, b)
}
if ok {
for _, prevErr := range e.prev {
b.WriteString("Previously thrown ")
printErr(prevErr, b)
}
}
}