chained errors introduced
This commit is contained in:
60
error.go
60
error.go
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user