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 was* 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. (I go into a bit more detail on this history in this video.)
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:
- If you want stack traces in your errors, use
github.com/pkg/errors.Errorfto wrap errors. - If you don’t care about stack traces, use
fmt.Errorffrom the standard library. - Never use
errors.Wrapfany more. It’s for backward compatibility.
*The github.com/pkg/errors package is no longer actively maintained. The repo has been archived, and is no longer accepting updates, but remains available for use.
**The standard library’s error package still does not include stack traces, so github.com/pkg/errors is still popular for that.