errors

package module
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 4, 2024 License: BSD-3-Clause Imports: 10 Imported by: 40

README

errors

Latest release Build status Go Report Card Documentation

Package errors contains additional functions, interfaces and structs for recording stack frames, applying basic formatting, working with goroutines, multiple errors and custom error types.

It is inspired by package golang.org/x/xerrors and is designed to be a drop-in replacement for it, as well as the standard library's errors package.

The errors.New and errors.Errorf functions create errors whose content is a text message and whom can trace stack frames. errors.Wrap and errors.Wrapf create errors by wrapping an existing error with a similar error like errors.New and errors.Errorf.

go get github.com/go-pogo/errors
import "github.com/go-pogo/errors"

Msg and Kind

Instead of defining error messages as global variables, it is possible to define them as constants using errors.Msg.

const ErrSomethingWentWrong errors.Msg = "something went wrong"

This same can be done with errors.Kind:

const InvalidOpError errors.Kind = "invalid operation error"
err = errors.WithKind(err, InvalidOpError)

errors.Is(err, InvalidOpError) // true

Formatting

Wrap an existing error with errors.WithFormatter to upgrade the error to include basic formatting. Formatting is done using xerrors.FormatError and thus the same verbs are supported. Any error created with this package implements the fmt.Formatter and xerrors.Formatter interfaces.

fmt.Printf("%+v", errors.WithFormatter(err))

Stack tracing

Every error can track stack trace information. Just wrap it with errors.WithStack and a complete stack trace is captured.

err = errors.WithStack(err)

An errors.StackTrace can be retrieved using errors.GetStackTrace. Printing the error results in a trace similar to:

invalid character 'i' looking for beginning of value:
	github.com/go-pogo/errors.ExampleWithStack
		/path/to/errors/examples_trace_test.go:43
	github.com/go-pogo/errors.ExampleWithStack.func1
		/path/to/errors/examples_trace_test.go:40

Disable stack tracing

Stack tracing comes with a performance cost. For production environments this cost can be undesirable. To disable stack tracing, compile your Go program with the "notrace" tag.

go build -tags=notrace

Catching panics

A convenient function is available to catch panics and store them as an error.

var err error
defer errors.CatchPanic(&err)

Backwards compatibility

Unwrap, Is, As are backwards compatible with the standard library's errors package and act the same.

Documentation

Additional detailed documentation is available at pkg.go.dev

Created with

License

Copyright © 2019-2024 Roel Schut. All rights reserved.

This project is governed by a BSD-style license that can be found in the LICENSE file.

Documentation

Overview

Package errors contains additional functions, interfaces and structs for recording stack frames, applying basic formatting, working with goroutines, multiple errors and custom error types.

It is inspired by package golang.org/x/xerrors and is designed to be a drop-in replacement for it, as well as the standard library's errors package.

The errors.New and errors.Errorf functions create errors whose content is a text message and whom can trace stack frames. errors.Wrap and errors.Wrapf create errors by wrapping an existing error with a similar error like errors.New and errors.Errorf.

Msg and Kind

Instead of defining error messages as global variables, it is possible to define them as constants using errors.Msg.

const ErrSomethingWentWrong errors.Msg = "something went wrong"

This same can be done with errors.Kind:

const InvalidOpError errors.Kind = "invalid operation error"
err = errors.WithKind(err, InvalidOpError)

errors.Is(err, InvalidOpError) // true

Formatting

Wrap an existing error with errors.WithFormatter to upgrade the error to include basic formatting. Formatting is done using xerrors.FormatError and thus the same verbs are supported. Any error created with this package implements the fmt.Formatter and xerrors.Formatter interfaces.

fmt.Printf("%+v", errors.WithFormatter(err))

Stack tracing

Every error can track stack trace information. Just wrap it with errors.WithStack and a complete stack trace is captured.

err = errors.WithStack(err)

An errors.StackTrace can be retrieved using errors.GetStackTrace. Printing the error results in a trace similar to:

invalid character 'i' looking for beginning of value:
	github.com/go-pogo/errors.ExampleWithStack
		/path/to/errors/examples_trace_test.go:43
	github.com/go-pogo/errors.ExampleWithStack.func1
		/path/to/errors/examples_trace_test.go:40

Disable stack tracing

Stack tracing comes with a performance cost. For production environments this cost can be undesirable. To disable stack tracing, compile your Go program with the "notrace" tag.

go build -tags=notrace

Catching panics

A convenient function is available to catch panics and store them as an error.

var err error
defer errors.CatchPanic(&err)

Backwards compatibility

Unwrap, Is, As are backwards compatible with the standard library's errors package and act the same.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Append

func Append(left, right error) error

Append creates a multi error from two non-nil errors. If left is already a multi error, the other error is appended to it. If either of the errors is nil, the other error is returned.

Example
type Result struct{}

unmarshal := func() (*Result, error) {
	dest := new(Result)
	err := json.Unmarshal([]byte("invalid"), &dest) // this wil result in an error
	return dest, WithStack(err)
}

closeSomething := func() error {
	return errors.New("some error occurred while closing something")
}

doSomething := func() (err error) {
	defer AppendFunc(&err, closeSomething)

	_, err = unmarshal()
	if err != nil {
		return err
	}
	return nil
}

err := doSomething()
fmt.Println(err)
Output:

multiple errors occurred:
[1/2] invalid character 'i' looking for beginning of value;
[2/2] some error occurred while closing something

func AppendFunc added in v0.7.2

func AppendFunc(dest *error, fn func() error)

AppendFunc appends the non-nil error result of fn to dest using AppendInto.

func AppendInto added in v0.9.0

func AppendInto(dest *error, errs ...error) (errored bool)

AppendInto appends multiple non-nil errors to a single multi error dest. When the value of dest is nil and errs only contains a single error, its value is set to the value of dest.

Important: when using AppendInto with defer, the pointer to the dest error must be a named return variable. For additional details see https://golang.org/ref/spec#Defer_statements.

func As

func As(err error, target interface{}) bool

As is an alias of errors.As. It finds the first error in err's chain that matches target, and if so, sets target to that error value and returns true.

func CatchPanic added in v0.6.0

func CatchPanic(dest *error)

CatchPanic recovers from a panic and wraps it in an error. It then calls AppendInto with the provided dest *error and wrapped panic. Use CatchPanic directly with defer. It is not possible to use CatchPanic inside a deferred function, like:

defer func(){ CatchPanic(&err }()
Example
var err error

done := make(chan struct{})
go func() {
	defer close(done)
	defer CatchPanic(&err)

	err = New("first error")
	panic("something bad happened")
}()

<-done
fmt.Println(err)
Output:

multiple errors occurred:
[1/2] first error;
[2/2] panic: something bad happened

func Cause added in v0.7.0

func Cause(err error) error

Cause walks through all wrapped errors and returns the last error in the chain.

func Errorf added in v0.8.0

func Errorf(format string, args ...interface{}) error

Errorf formats an error message according to a format specifier and provided arguments with fmt.Errorf, and creates a new error similar to New.

err := errors.Errorf("my error %s", "message")
err := errors.Errorf("my error: %w", cause)

func FatalOnErr added in v0.7.2

func FatalOnErr(err error)

FatalOnErr prints the error to stderr and exits the program with an exit code that is not 0. When err is an ExitCoder its exit code is used.

func Filter

func Filter(errors []error) []error

Filter returns a slice of errors without nil values in between them. It returns the slice with the length of the amount of non-nil errors but keeps its original capacity.

func FormatError

func FormatError(err error, state fmt.State, verb rune)

FormatError calls the FormatError method of err with a Printer configured according to state and verb, and writes the result to state. It will wrap err If err is not a Formatter it will wrap err, so it is capable of basic error formatting using WithFormatter.

Example
doSomething := func() error {
	return New("something happened")
}

err := doSomething()
var fmt = new(ignoreThisLineUseFmtPackageInActualCode)
fmt.Printf("%+v\n", err)
Output:

something happened:
    github.com/go-pogo/errors.ExampleFormatError
        /path/to/errors/examples_trace_test.go:23
    github.com/go-pogo/errors.ExampleFormatError.func1
        /path/to/errors/examples_trace_test.go:20

func GetExitCode

func GetExitCode(err error) int

GetExitCode returns an exit status code if the error implements the ExitCoder interface. If not, it returns 0.

func GetExitCodeOr added in v0.6.1

func GetExitCodeOr(err error, or int) int

GetExitCodeOr returns the exit status code from the first found ExitCoder in err's error chain. If none is found, it returns the provided value or.

func GetStatusCode added in v0.7.6

func GetStatusCode(err error) int

GetStatusCode returns the status code if the error implements the StatusCoder interface. If not, it returns 0.

func GetStatusCodeOr added in v0.7.6

func GetStatusCodeOr(err error, or int) int

GetStatusCodeOr returns the status code from the first found StatusCoder in err's error chain. If none is found, it returns the provided value or.

func GetTime added in v0.7.0

func GetTime(err error) (time.Time, bool)

GetTime returns the time.Time of the last found Timer in err's error chain. If none is found, it returns the provided value or.

func Is

func Is(err, target error) bool

Is reports whether any error in err's chain matches target. It is fully compatible with both errors.Is and xerrors.Is.

An error is considered to match a target if it is equal to that target or if it implements a method Is(error) bool such that Is(target) returns true.

func Join added in v0.7.5

func Join(errs ...error) error

Join returns a MultiError when more than one non-nil errors are provided. It returns a single error when only one error is passed, and nil if no non-nil errors are provided.

func Must

func Must(args ...interface{})

Must panics when any of the given args is a non-nil error. Its message is the error message of the first encountered error.

func New

func New(msg interface{}) error

New creates a new error which implements the StackTracer, Wrapper and Formatter interfaces. Argument msg can be either a string or Msg.

err := errors.New("my error message")
err := errors.New(errors.Msg("my error message"))

New records a stack trace at the point it was called. Each call returns a distinct error value even if msg is identical. It will return nil if msg is nil. Use WithStack to wrap an existing error with a StackTracer and Formatter.

Example
doSomething := func() error {
	return New("something happened")
}

err := doSomething()
fmt.Println(err)
Output:

something happened

func Newf deprecated

func Newf(format string, args ...interface{}) error

Newf formats an error message according to a format specifier and provided arguments.

Deprecated: Use Errorf instead.

func Opaque

func Opaque(err error) error

Opaque is an alias of xerrors.Opaque. It returns an error with the same error formatting as err but that does not match err and cannot be unwrapped.

func PanicOnErr added in v0.9.0

func PanicOnErr(err error)

PanicOnErr panics when err is not nil.

func PrintError

func PrintError(p Printer, err error)

PrintError prints the error err with the provided Printer and formats and prints the error's stack frames.

func PrintFrames added in v0.8.0

func PrintFrames(p Printer, cf *runtime.Frames)

PrintFrames prints a complete stack of *runtime.Frames using Printer p.

func Unembed added in v0.7.0

func Unembed(err error) error

Unembed recursively unwraps all Embedder errors and returns the (original) error that was wrapped with extra context. If err is not an Embedder, Unembed returns err as provided.

func Unwrap

func Unwrap(err error) error

Unwrap is an alias of errors.Unwrap. It returns the result of calling the Unwrap method on err, if err's type contains an Unwrap method returning error. Otherwise, Unwrap returns nil.

func UnwrapAll

func UnwrapAll(err error) []error

UnwrapAll returns the complete chain of errors, starting with the supplied error and ending with the root cause error.

func WithKind

func WithKind(err error, kind Kind) error

WithKind wraps an error with Kind, therefore extending the error chain.

Example
const (
	ErrSomethingWentWrong Msg  = "something went wrong"
	SomeKindOfError       Kind = "some kind of error"
)

doSomethingElse := func() error {
	return New(ErrSomethingWentWrong)
}
doSomething := func() error {
	err := doSomethingElse()
	return WithKind(err, SomeKindOfError)
}

err := doSomething()
fmt.Println(err)
Output:

some kind of error: something went wrong

func Wrap

func Wrap(cause error, msg interface{}) error

Wrap creates a new error, which implements the StackTracer, Wrapper and Formatter interfaces, that wraps around the causing error. Argument msg can be either a string or Msg.

err = errors.Wrap(err, "my error message")
err = errors.Wrap(err, errors.Msg("my error message"))

Wrap records a stack trace at the point it was called. Each call returns a distinct error value even if cause and msg are identical. Wrap will return nil when cause is nil, and it will return the provided cause when msg is nil.

func WrapPanic

func WrapPanic(prefix string)

WrapPanic wraps a panicking sequence with the given prefix. It then panics again.

func Wrapf

func Wrapf(cause error, format string, args ...interface{}) error

Wrapf formats an error message according to a format specifier and provided arguments with fmt.Errorf, and creates a new error similar to Wrap.

err = errors.Wrapf(err, "my error %s", "message")

Types

type Embedder added in v0.7.0

type Embedder interface {
	error
	Unembed() error
}

An Embedder unwraps an embedded error.

type ExitCoder

type ExitCoder interface {
	error
	ExitCode() int
}

ExitCoder interfaces provide access to an exit code.

func WithExitCode

func WithExitCode(err error, exitCode int) ExitCoder

WithExitCode adds an exit status code to the error which may indicate a fatal error. The exit code can be supplied to os.Exit to terminate the program immediately.

type ExitCoderSetter added in v0.7.0

type ExitCoderSetter interface {
	ExitCoder
	SetExitCode(int)
}

ExitCoderSetter interfaces provide access to an exit code which can be changed.

type Formatter added in v0.7.4

type Formatter = xerrors.Formatter

A Formatter formats error messages and prints them to a Printer. It is an alias of xerrors.Formatter.

func WithFormatter

func WithFormatter(err error) Formatter

WithFormatter wraps the error with a Formatter that is capable of basic error formatting. It returns the provided error as is if it already is a Formatter, or nil when err is nil.

type Frame added in v0.8.0

type Frame uintptr

func (Frame) FileLine added in v0.8.0

func (fr Frame) FileLine() (file string, line int)

FileLine returns the file name and line number of the source code corresponding to the program counter PC.

func (Frame) Func added in v0.8.0

func (fr Frame) Func() *runtime.Func

Func returns a *runtime.Func describing the function that contains the given program counter address, or else nil.

func (Frame) PC added in v0.8.0

func (fr Frame) PC() uintptr

PC is the program counter for the location in this frame.

type Kind

type Kind string

Kind describes the kind/type of error that has occurred. For example "auth error", "unmarshal error", etc. Errors can be of the same Kind but still contain different underlying causes. It is recommended to define each Kind as a constant.

const UnknownKind Kind = ""

UnknownKind is the default Kind for errors that are created without a distinct Kind.

func GetKind

func GetKind(err error) Kind

GetKind returns the Kind of the error if it is added with WithKind. If not, it returns UnknownKind.

func GetKindOr added in v0.6.1

func GetKindOr(err error, or Kind) Kind

GetKindOr returns the Kind of the error if it is added with WithKind. If not, it returns the provided Kind or.

func (Kind) As added in v0.7.0

func (k Kind) As(target interface{}) bool

func (Kind) Error added in v0.7.0

func (k Kind) Error() string

func (Kind) GoString added in v0.7.0

func (k Kind) GoString() string

func (Kind) Is added in v0.7.0

func (k Kind) Is(target error) bool

func (Kind) String

func (k Kind) String() string

String returns the string representation of Kind.

type Msg added in v0.7.0

type Msg string

Msg is a string alias which can also be used as a basic error. This is particularly useful for defining constants of known errors in your library or application.

const ErrMyErrorMessage errors.Msg = "my error message"
const ErrAnotherError   errors.Msg = "just another error"

A new error can be constructed from any Msg with New and is considered to be equal when comparing with Is.

err := errors.New(ErrMyErrorMessage)
errors.Is(err, ErrMyErrorMessage) // true
Example
const ErrSomethingHappened Msg = "something happened"

doSomething := func() error {
	return New(ErrSomethingHappened)
}

err := doSomething()
fmt.Println(err)
Output:

something happened

func (Msg) As added in v0.7.0

func (m Msg) As(target interface{}) bool

func (Msg) Error added in v0.7.0

func (m Msg) Error() string

func (Msg) GoString added in v0.7.0

func (m Msg) GoString() string

func (Msg) Is added in v0.7.0

func (m Msg) Is(target error) bool

func (Msg) String added in v0.7.0

func (m Msg) String() string

type MultiError

type MultiError interface {
	error
	Unwrap() []error
}

MultiError is an error which unwraps into multiple underlying errors.

type Printer added in v0.7.4

type Printer = xerrors.Printer

A Printer prints a formatted error. It is an alias of xerrors.Printer.

type StackTrace added in v0.7.0

type StackTrace struct {

	// Skip n frames when formatting with Format, so overlapping frames from
	// previous errors are not printed.
	Skip uint
	// contains filtered or unexported fields
}

func GetStackTrace added in v0.7.0

func GetStackTrace(err error) *StackTrace

GetStackTrace returns a *StackTrace if err is a StackTracer or nil otherwise.

func (*StackTrace) CallersFrames added in v0.8.0

func (st *StackTrace) CallersFrames() *runtime.Frames

CallersFrames returns a *runtime.Frames by calling runtime.CallersFrame with the captured stack trace frames as callers argument.

func (*StackTrace) Format added in v0.7.0

func (st *StackTrace) Format(printer xerrors.Printer)

Format formats the slice of xerrors.Frame using a xerrors.Printer. It will Skip n frames when printing so no overlapping frames with underlying errors are displayed.

func (*StackTrace) Frames added in v0.7.0

func (st *StackTrace) Frames() []Frame

Frames returns a []Frame. Use CallersFrames instead if you want to access the whole stack trace of frames.

func (*StackTrace) Len added in v0.7.0

func (st *StackTrace) Len() uint

Len returns the amount of captures frames.

func (*StackTrace) String added in v0.7.0

func (st *StackTrace) String() string

String returns a formatted string of the complete stack trace.

type StackTracer

type StackTracer interface {
	error

	// StackTrace returns a stack of traces frames.
	StackTrace() *StackTrace
}

StackTracer interfaces provide access to a stack of traced StackTrace.

func WithStack added in v0.7.0

func WithStack(err error) StackTracer

WithStack gets a stack trace at the point WithStack was called and adds it to the error. If err is nil, WithStack returns nil.

Example
type Result struct{}

doSomething := func() (*Result, error) {
	dest := new(Result)
	err := json.Unmarshal([]byte("invalid"), &dest) // this wil result in an error
	return dest, WithStack(err)
}

_, err := doSomething()
var fmt = new(ignoreThisLineUseFmtPackageInActualCode)
fmt.Printf("%+v\n", err)
Output:

invalid character 'i' looking for beginning of value:
    github.com/go-pogo/errors.ExampleWithStack
        /path/to/errors/examples_trace_test.go:43
    github.com/go-pogo/errors.ExampleWithStack.func1
        /path/to/errors/examples_trace_test.go:40

type StatusCoder added in v0.7.6

type StatusCoder interface {
	error
	StatusCode() int
}

StatusCoder interfaces provide access to a (http) status code.

func WithStatusCode added in v0.7.6

func WithStatusCode(err error, statusCode int) StatusCoder

WithStatusCode adds a (http) status code to the error which can be retrieved using GetStatusCode and may be set to a http.ResponseWriter.

type StatusCoderSetter added in v0.7.6

type StatusCoderSetter interface {
	StatusCoder
	SetStatusCode(int)
}

type Timer added in v0.7.0

type Timer interface {
	error
	Time() time.Time
}

Timer interfaces provide access to a time.Time indicating when the error occurred.

func WithTime added in v0.7.0

func WithTime(err error, when time.Time) Timer

WithTime adds time information to the error. It does so by wrapping the error with a Timer, or update/set the time when error is a TimerSetter. It will return nil when the provided error is nil.

type TimerSetter added in v0.7.0

type TimerSetter interface {
	Timer
	SetTime(time.Time)
}

type Wrapper added in v0.7.0

type Wrapper interface {
	error
	xerrors.Wrapper
}

A Wrapper provides context around another error, which can be retrieved with Unwrap.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL