Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between errors.Wrapf(), errors.Errorf(), and fmt.Errorf()?

What's the difference between these three functions from Go's standard packages:

  • errors.Wrapf()

Wrapf returns an error annotating err with a stack trace at the point Wrapf is called, and the format specifier. If err is nil, Wrapf returns nil.

  • errors.Errorf(), provided an error via %w format variable

Errorf formats according to a format specifier and returns the string as a value that satisfies error. Errorf also records the stack trace at the point it was called.

  • fmt.Errorf(), provided an error via %w format variable

Errorf formats according to a format specifier and returns the string as a value that satisfies error.

If the format specifier includes a %w verb with an error operand, the returned error will implement an Unwrap method returning the operand. It is invalid to include more than one %w verb or to supply it with an operand that does not implement the error interface. The %w verb is otherwise a synonym for %v.

When one should be used instead of others?

like image 487
leventov Avatar asked May 21 '20 11:05

leventov


1 Answers

First, a correction:

github.com/pkg/errors is not part of the standard library! The standard errors package has a much smaller API.

That said, github.com/pkg/errors is very popular, and is maintained by some prominent Gophers. It is, however, largely (though not completely*) obsoleted by Go 1.13's extended error support.

Understanding the difference between those three functions requires a bit of a history lesson.

Prior to Go 1.13, there was no officially-recognized way to "wrap" errors. github.com/pkg/errors filled this gap with the Wrap and Wrapf methods. This allowed wrapping an error with additional context (including a stack trace), while retaining the original error in pristine form.

When Go 1.13 was in development, github.com/pkg/errors was used to influence the new API, but the final version differed slightly. Rather than Wrap and Wrapf methods, they decided to extend the fmt.Errorf method with a new %w verb, which would perform error wrapping for you.

This means that the following bits of code are roughly* equivalent:

    import "github.com/pkg/errors"

    /* snip */

    return errors.Wrapf(err, "bad things")
    // +build go1.13

    import "fmt"

    /* snip */
    return fmt.Errorf("bad things: %w", err)

When Go 1.13 came out, and the %w verb was added to fmt.Errorf, github.com/pkg/errors followed suit and added the same support, so now Wrapf is effectively obsolete.

So this brings us to the present day recommendations:

  1. If you want stack traces in your errors, use github.com/pkg/errors.Errorf to wrap errors.
  2. If you don't care about stack traces, use fmt.Errorf from the standard library.
  3. Never use errors.Wrapf any more. It's for backward compatibility.

*The standard library's error package still does not include stack traces, so github.com/pkg/errors is still popular for that.

like image 121
Flimzy Avatar answered Sep 21 '22 13:09

Flimzy