add errx
This commit is contained in:
parent
0a9f6491b4
commit
ff30f6c3d6
6 changed files with 302 additions and 1 deletions
89
errx.go
Normal file
89
errx.go
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
// Package errx provides a small error wrapper that records the operation
|
||||
// where each error occurred, producing a readable chain in place of a
|
||||
// runtime stack trace.
|
||||
//
|
||||
// Each function declares its own operation name and wraps the underlying
|
||||
// error with that op (and an optional message). The resulting error
|
||||
// formats top-down as a colon-joined breadcrumb:
|
||||
//
|
||||
// users.Get: lookup failed: db.Query: connection refused
|
||||
//
|
||||
// errx is fully compatible with errors.Is and errors.As via Unwrap.
|
||||
//
|
||||
// Basic usage:
|
||||
//
|
||||
// const op = "users.Get"
|
||||
// row, err := db.Query(...)
|
||||
// if err != nil {
|
||||
// return errx.Wrap(op, err)
|
||||
// }
|
||||
package errx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Error is the concrete error type produced by this package. Op identifies
|
||||
// the operation that failed; Msg adds optional context; Err is the
|
||||
// underlying error being wrapped (may be nil).
|
||||
type Error struct {
|
||||
// Op is the operation name, conventionally "package.Func" or
|
||||
// "Receiver.Method".
|
||||
Op string
|
||||
// Msg is an optional context message describing what went wrong.
|
||||
Msg string
|
||||
// Err is the underlying error being wrapped. May be nil.
|
||||
Err error
|
||||
}
|
||||
|
||||
// Error returns the colon-joined chain of op, message, and wrapped error.
|
||||
// Empty pieces are omitted.
|
||||
func (e *Error) Error() string {
|
||||
parts := make([]string, 0, 3)
|
||||
if e.Op != "" {
|
||||
parts = append(parts, e.Op)
|
||||
}
|
||||
if e.Msg != "" {
|
||||
parts = append(parts, e.Msg)
|
||||
}
|
||||
if e.Err != nil {
|
||||
parts = append(parts, e.Err.Error())
|
||||
}
|
||||
return strings.Join(parts, ": ")
|
||||
}
|
||||
|
||||
// Unwrap returns the wrapped error, enabling errors.Is and errors.As.
|
||||
func (e *Error) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// New returns a new error tagged with op and the static message msg.
|
||||
func New(op, msg string) error {
|
||||
return &Error{Op: op, Msg: msg}
|
||||
}
|
||||
|
||||
// Newf returns a new error tagged with op and a message formatted per
|
||||
// fmt.Sprintf rules.
|
||||
func Newf(op, format string, args ...any) error {
|
||||
return &Error{Op: op, Msg: fmt.Sprintf(format, args...)}
|
||||
}
|
||||
|
||||
// Wrap returns an error tagged with op that wraps err. If err is nil,
|
||||
// Wrap returns nil so callers can write `return errx.Wrap(op, doThing())`
|
||||
// without a guard.
|
||||
func Wrap(op string, err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &Error{Op: op, Err: err}
|
||||
}
|
||||
|
||||
// Wrapf returns an error tagged with op that wraps err and adds a message
|
||||
// formatted per fmt.Sprintf rules. If err is nil, Wrapf returns nil.
|
||||
func Wrapf(op string, err error, format string, args ...any) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &Error{Op: op, Msg: fmt.Sprintf(format, args...), Err: err}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue