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.