Code-Memo

Custom errors

In Go, errors are values implementing the error interface: a single method Error() string.

Creating errors
import "errors"
import "fmt"

var ErrNotFound = errors.New("not found")

func parse(s string) error {
	return fmt.Errorf("parse %q: %w", s, ErrInvalid)
}
Wrapping with %w

Use fmt.Errorf("...: %w", err) so callers can unwrap with errors.Is and errors.As.

if errors.Is(err, ErrNotFound) {
	// handle
}

var p *os.PathError
if errors.As(err, &p) {
	// path-specific
}
Sentinel errors

Package-level var ErrXxx = errors.New(...) values are compared with errors.Is, not == on a wrapped chain (unless you know it is the exact value).

Custom error types
type ValidationError struct {
	Field string
	Msg   string
}

func (e *ValidationError) Error() string {
	return e.Field + ": " + e.Msg
}

Use errors.As to recover the concrete type.

When to panic

Libraries should return errors. panic is for programming bugs or unrecoverable situations; recover is rare and usually only at package boundaries (e.g. HTTP handlers middleware).

Error handling style