Skip to content

Instantly share code, notes, and snippets.

@StevenACoffman
Last active September 14, 2023 11:48
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StevenACoffman/5be27a265619e19123db0bedf4da1617 to your computer and use it in GitHub Desktop.
Save StevenACoffman/5be27a265619e19123db0bedf4da1617 to your computer and use it in GitHub Desktop.
Errors in Go

This is my notes from a few articles:

Some error values are mostly just used for control flow. For example, "Access Denied", or "Authentication Required".

In my opinion, you should only add stack trace to an error which is potentially going to break your program. A logical error like we have seen in the authorization example does not need a track state. But since Wrap method can be used to ammend original error message which is also called as annotating an error, the choice is up to you.

The types of errors that would bubble up to be a 500 Internal Server Error generally require investigation by a developer. In these cases, a stacktrace (and ideally other contextual information) is incredibly valuable.

There are a few popular contenders for contemporary error handling in Go.

  • Go 1.13 errors / golang.org/x/xerrors
  • github.com/pkg/errors
  • cockroachdb/errors

Problems with Go 1.13 errors compared to github.com/pkg/errors:

  1. Replace Wrap with format parameter : %w . Looks simplify the code, but this approach loses compile-time checking. If : %w is not the tail of format string(e.g., "foo : %w bar"), or colon is missing (e.g., "foo %w"), or the space between colon and percent sign is missing (e.g., "foo:%w"), the wrapping will fail without any warning
  2. What’s more serious is that you have to check the condition err != nil before calling xerrors.Errorf. This actually does not simplify the work of the developer at all
  3. Unlike golang.org/x/xerrors, Go 1.13 errors dropped support for call stack output. And according to the official statement, there is no schedule for this. So github.com/pkg/errors is much better choice at the moment.

Problems with cockroachdb/errors:

  1. It is a heavy swiss army knife that doesn't load in the Goland Playground so my co-workers will never let adopt it. πŸ˜…
  2. It might not be future compatible with some possible future Go standard lib error stacktrace capture mechanism.

It has very lovely output though. 😏

github.com/pkg/errors quirks

If we use %v as format parameter, we’ll get an one-line output string, contains all contextual text in the order of call stack. If change the format parameter to %+v, we’ll get the complete call stack.

If you want to simply wrap error with attach call stack, no additional contextual text is needed, then use WithStack

func foo() error {
   return errors.WithStack(sql.ErrNoRows)
}

Note: When use Wrap, WithMessage or WithStack, if the err parameter is nil, then nil will be returned, which means that we don’t need to check err != nil condition before calling the method. This keeps the code simple.

Feature comparison (abridged from https://github.com/cockroachdb/errors/)

Feature Go's <1.13 errors github.com/pkg/errors Go 1.13 errors/xerrors cockroachdb/errors
error constructors (New, Errorf etc) βœ” βœ” βœ” βœ”
error causes (Cause / Unwrap) βœ” βœ” βœ”
cause barriers (Opaque / Handled) βœ” βœ”
errors.As(), errors.Is() βœ” βœ”
automatic error wrap when format ends with : %w βœ” βœ”
standard wrappers with efficient stack trace capture βœ” βœ”
transparent protobuf encode/decode with forward compatibility βœ”
errors.Is() recognizes errors across the network βœ”
comprehensive support for PII-free reportable strings βœ”
support for both Cause() and Unwrap() go#31778 βœ”
errors.FormatError(), Formatter, Printer (under construction) βœ”

Further reading

@szthanatos
Copy link

mark.
very clear & make sense πŸ‘

@StevenACoffman
Copy link
Author

StevenACoffman commented Mar 28, 2023

@szthanatos Thanks! You might want to check out https://github.com/StevenACoffman/simplerr which is a lightweight version of cockroachdb/errors or https://github.com/StevenACoffman/comparerr which demonstrates the output of a lot of popular Go error libraries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment