Simple custom error wrapper utility library for my Go projects.
| .gitignore | ||
| errx.go | ||
| errx_test.go | ||
| example_test.go | ||
| go.mod | ||
| LICENSE | ||
| README.md | ||
| Taskfile.yml | ||
errx
Simple custom error wrapper utility library for my Go projects.
errx records the operation where each error happened and chains those
operations together as the error bubbles up. The result is a readable
breadcrumb instead of a runtime stack trace:
users.Get: user=42: db.Query: connection refused
Usage
Each function declares its op and wraps errors as it returns them:
import "git.juancwu.dev/juancwu/errx"
func (s *Store) Get(id int) (*User, error) {
const op = "users.Get"
row, err := s.db.Query(id)
if err != nil {
return nil, errx.Wrapf(op, err, "user=%d", id)
}
if row == nil {
return nil, errx.New(op, "not found")
}
return row, nil
}
The four constructors:
errx.New(op, msg) // fresh error, static msg
errx.Newf(op, format, args...) // fresh error, formatted msg
errx.Wrap(op, err) // wrap, no extra msg (nil-safe)
errx.Wrapf(op, err, format, args...) // wrap with formatted msg (nil-safe)
Wrap and Wrapf return nil when passed a nil error, so you can chain
them without an extra guard:
return errx.Wrap(op, s.commit())
Interop
*errx.Error implements Unwrap, so errors.Is and errors.As walk the
chain as expected:
if errors.Is(err, io.EOF) { ... }
var e *errx.Error
if errors.As(err, &e) {
log.Printf("op=%s", e.Op)
}
Development
This repo uses Task as its task runner. After cloning:
task install:tools # installs github.com/mfridman/tparse
task # vet + tests
Common targets:
| Task | What it does |
|---|---|
task |
vet + test (the default) |
task test |
go test ./... piped through tparse |
task test:race |
tests under the race detector |
task vet |
go vet ./... |
task fmt |
gofmt -w . |
task tidy |
go mod tidy |