On Fri, Dec 31, 2021 at 5:12 AM Brian Candler <b.cand...@pobox.com> wrote:

> On Friday, 31 December 2021 at 08:10:49 UTC Henry wrote:
>
>> The purpose of error wrapping is to give contextual information about the
>> error. It is supposed to help you understand and locate the error. For
>> instance, *"invalid filename"* is not particularly useful when compared
>> to *"fail to load customer data: invalid filename"*. Error wrapping is a
>> stack trace in a human-friendly language.
>
>
> I disagree with that explanation, because what you describe can be done
> without wrapping:
> return fmt.Errorf("Failed to load customer data: %v", err)
> or with wrapping:
> return fmt.Errorf("Failed to load customer data: %w", err)
>
> Both provide exactly the same human-friendly trace.  The difference is
> that with the wrapped error, the error value can be destructured to
> retrieve the "cause" error object, and hence to match on that object. It's
> an invitation to your API consumer to couple directly to error types which
> your code doesn't return, but which originate from elsewhere, typically
> system libraries or third-party libraries.
>
> The question then is, under what circumstances is that a good idea?  It
> depends.  Perhaps one example is if your code is using an underlying
> database API, and you are happy to expose raw database-level errors.  That
> allows your own library to wash its hands of responsibility of how to deal
> with these, and let the consumer deal with them if it wants to.  (Was it a
> temporary connection error? Was it a uniqueness constraint violation?  Not
> My Problemâ„¢)
>

There's a good argument to be made against wrapping errors at
api-boundaries in some cases. IMO, that's something that's definitely
case-by-case as there are situations where bubbling up the underlying error
is 100% the right thing to do.
e.g. io/fs.FS <https://pkg.go.dev/io/fs#FS> implementations are
constrained to returning the io/fs.PathError
<https://pkg.go.dev/io/fs#PathError> type by the interface documentation in
some cases. However, there are specific underlying sentinel values that
should be bubbled up and accessible.

IMO, within a package (or somewhat intentionally nebulously: "between API
boundaries"), it's generally a good idea to use error wrapping so outer
layers can make the actual wrapping, unwrapping, switching decisions.
By using error-wrapping, you're free to break functions up and add context
as it bubbles up, without losing the ability to switch on the original
error. (or at least use errors.Is or errors.As)

As an example of a the above trade-off, here's an io/fs.FS implementation I
pushed up recently:
https://gitlab.com/dfinkel/go-safefs/-/blob/ca532e3c5c5c/fs_linux.go#L78-105
It's switching on errno values and wrapping specific sentinel errors with
context for the errno values I knew I could see, with specific diagnostics
for those errors.

Worth noting: stack traces rarely have argument values, and don't generally
have other context information, e.g. EMFILE handling specifically checks
the rlimit to get the fd limit value to include in the error message. Stack
traces are nice for the programmer if they've opened the right version of
the code, but useless for everyone else. Errors with context are orders of
magnitude more useful if written correctly. (one of the reasons I don't
like exceptions is that most of the time you just get the stack trace and
original error, which is only barely useful for debugging if you have the
most trivial bugs)

> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/fa907dec-1dc7-4909-9743-4d91eb146481n%40googlegroups.com
> <https://groups.google.com/d/msgid/golang-nuts/fa907dec-1dc7-4909-9743-4d91eb146481n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CANrC0BgDVcWOxf_hvnPF7yAUoG3JJ16cFHVVhjZpX-bSS8jNCw%40mail.gmail.com.

Reply via email to