From e438d5ad6f6c6ce6756036c54a768310bd2295ba Mon Sep 17 00:00:00 2001 From: "Jonathan A. Sternberg" Date: Mon, 22 Jul 2024 11:38:06 -0500 Subject: [PATCH] Add attach and mask functions for joining errors in a different way The `Attach` and `Mask` functions create a new error node that returns the error message from one node, but creates a structure where the additional errors are in the error chain and can be discovered with `errors.Is` and `errors.As`. Signed-off-by: Jonathan A. Sternberg --- errors.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/errors.go b/errors.go index 4827d8c..10d7d66 100644 --- a/errors.go +++ b/errors.go @@ -409,3 +409,37 @@ func (c customMessage) As(target any) bool { func (c customMessage) Error() string { return c.msg } + +// Attach will join the extra errors to the base error where +// only the base error is part of the message but all errors +// are wrapped at the same level. +func Attach(base error, extra ...error) error { + return &attachedError{ + error: base, + wrapped: append([]error{base}, extra...), + } +} + +// Mask will join the extra errors where the base error is +// part of the message but the extra errors are joined earlier +// in the chain and would mask the base error when used with +// errors.Is or errors.As. +func Mask(base error, extra ...error) error { + return &attachedError{ + error: base, + wrapped: append(extra, base), + } +} + +// attachedError is used to attach errors to a base +// error. The attached errors will be hidden from view when +// being printed but will show up when errors.Is or errors.As +// are used. +type attachedError struct { + error + wrapped []error +} + +func (e *attachedError) Unwrap() []error { + return e.wrapped +}