12 — Errors¶
Go's error is an interface with one method, and until Go 1.13 that was the whole of it: a function returned an error, the caller printed it or compared it with a sentinel. Go 1.13 added a structure underneath — an error may wrap another, fmt.Errorf's %w does it in one verb, and errors.Is, errors.As and errors.Unwrap walk the chain that results — and Go 1.20 turned the chain into a tree with errors.Join and multiple %w. This chapter measures that machinery on Go 1.25: what wraps, what does not, what Is and As find, where the panics are, and which design decisions (wrap or hide, sentinel or type) the tooling can and cannot check.
The reader should know that error is an interface and how a method set decides which type satisfies it — 11 — Interfaces and method sets — and, for the goroutine side of errors, A goroutine has no handle, Cancel with a cause and The first error cancels the rest, which this chapter links back to rather than repeats.
| Lesson | The one thing |
|---|---|
%w wraps and errors.Is sees through it |
%w keeps the cause and %v prints it away; errors.Is finds a sentinel at any depth, == sees only the outer value, Unwrap takes one layer, and an Is method extends matching |
errors.As finds a type in the chain |
As fills a pointer to the stored type — pointer or value, as the method set decides — through any wrapping; a wrong target panics with one of three recorded messages |
errors.Join holds many errors in one |
Join and a two-%w Errorf make a tree that Is and As search; Error() joins with newlines, a join of nils is nil, and errors.Unwrap does not look inside |
An error type wraps through Unwrap |
Unwrap() error or Unwrap() []error on your own type; wrap when the cause is API, hide it with %v when it is a detail; lower case, no trailing stop |
| Companion | What it holds |
|---|---|
| Errors: the compiler errors | seven refusals recorded verbatim — unused err, missing return, need type assertion, errors.Wrap, a string as an error, errors.New with arguments, the wrong Error signature |
| Errors: what go vet and gofmt catch | printf, errorsas, unusedresult and stdmethods on error code, run and recorded; the shadowed err, the typed nil, == on a wrapped sentinel and a cause lost to %v that no tool sees |
| Errors: resources | the package docs, the 1.13 blog post and design document, the release notes, the book chapters and sections, two talks, and what to read with care |
Planned¶
- Stack traces: the standard
errorcarries none;runtime/debug.Stackat the point of creation, and whatlog/slogdoes with an error value. errors.ErrUnsupported(Go 1.21) and theAs(any) boolmethod a type may provide, so it can be treated as another type.- Errors in tests:
t.Fatalvs returning,errors.Isin assertions, and testing a package's documented sentinels. - Panics as errors: converting a recovered panic into an
errorat an API boundary — after 13 — Defer, panic and recover.