| // Package errors provides simple error handling primitives. | |
| // | |
| // The traditional error handling idiom in Go is roughly akin to | |
| // | |
| // if err != nil { | |
| // return err | |
| // } | |
| // | |
| // which when applied recursively up the call stack results in error reports | |
| // without context or debugging information. The errors package allows | |
| // programmers to add context to the failure path in their code in a way | |
| // that does not destroy the original value of the error. | |
| // | |
| // Adding context to an error | |
| // | |
| // The errors.Wrap function returns a new error that adds context to the | |
| // original error by recording a stack trace at the point Wrap is called, | |
| // together with the supplied message. For example | |
| // | |
| // _, err := ioutil.ReadAll(r) | |
| // if err != nil { | |
| // return errors.Wrap(err, "read failed") | |
| // } | |
| // | |
| // If additional control is required, the errors.WithStack and | |
| // errors.WithMessage functions destructure errors.Wrap into its component | |
| // operations: annotating an error with a stack trace and with a message, | |
| // respectively. | |
| // | |
| // Retrieving the cause of an error | |
| // | |
| // Using errors.Wrap constructs a stack of errors, adding context to the | |
| // preceding error. Depending on the nature of the error it may be necessary | |
| // to reverse the operation of errors.Wrap to retrieve the original error | |
| // for inspection. Any error value which implements this interface | |
| // | |
| // type causer interface { | |
| // Cause() error | |
| // } | |
| // | |
| // can be inspected by errors.Cause. errors.Cause will recursively retrieve | |
| // the topmost error that does not implement causer, which is assumed to be | |
| // the original cause. For example: | |
| // | |
| // switch err := errors.Cause(err).(type) { | |
| // case *MyError: | |
| // // handle specifically | |
| // default: | |
| // // unknown error | |
| // } | |
| // | |
| // Although the causer interface is not exported by this package, it is | |
| // considered a part of its stable public interface. | |
| // | |
| // Formatted printing of errors | |
| // | |
| // All error values returned from this package implement fmt.Formatter and can | |
| // be formatted by the fmt package. The following verbs are supported: | |
| // | |
| // %s print the error. If the error has a Cause it will be | |
| // printed recursively. | |
| // %v see %s | |
| // %+v extended format. Each Frame of the error's StackTrace will | |
| // be printed in detail. | |
| // | |
| // Retrieving the stack trace of an error or wrapper | |
| // | |
| // New, Errorf, Wrap, and Wrapf record a stack trace at the point they are | |
| // invoked. This information can be retrieved with the following interface: | |
| // | |
| // type stackTracer interface { | |
| // StackTrace() errors.StackTrace | |
| // } | |
| // | |
| // The returned errors.StackTrace type is defined as | |
| // | |
| // type StackTrace []Frame | |
| // | |
| // The Frame type represents a call site in the stack trace. Frame supports | |
| // the fmt.Formatter interface that can be used for printing information about | |
| // the stack trace of this error. For example: | |
| // | |
| // if err, ok := err.(stackTracer); ok { | |
| // for _, f := range err.StackTrace() { | |
| // fmt.Printf("%+s:%d\n", f, f) | |
| // } | |
| // } | |
| // | |
| // Although the stackTracer interface is not exported by this package, it is | |
| // considered a part of its stable public interface. | |
| // | |
| // See the documentation for Frame.Format for more details. | |
| package errors | |
| import ( | |
| "fmt" | |
| "io" | |
| ) | |
| // New returns an error with the supplied message. | |
| // New also records the stack trace at the point it was called. | |
| func New(message string) error { | |
| return &fundamental{ | |
| msg: message, | |
| stack: callers(), | |
| } | |
| } | |
| // Errorf formats according to a format specifier and returns the string | |
| // as a value that satisfies error. | |
| // Errorf also records the stack trace at the point it was called. | |
| func Errorf(format string, args ...interface{}) error { | |
| return &fundamental{ | |
| msg: fmt.Sprintf(format, args...), | |
| stack: callers(), | |
| } | |
| } | |
| // fundamental is an error that has a message and a stack, but no caller. | |
| type fundamental struct { | |
| msg string | |
| *stack | |
| } | |
| func (f *fundamental) Error() string { return f.msg } | |
| func (f *fundamental) Format(s fmt.State, verb rune) { | |
| switch verb { | |
| case 'v': | |
| if s.Flag('+') { | |
| io.WriteString(s, f.msg) | |
| f.stack.Format(s, verb) | |
| return | |
| } | |
| fallthrough | |
| case 's': | |
| io.WriteString(s, f.msg) | |
| case 'q': | |
| fmt.Fprintf(s, "%q", f.msg) | |
| } | |
| } | |
| // WithStack annotates err with a stack trace at the point WithStack was called. | |
| // If err is nil, WithStack returns nil. | |
| func WithStack(err error) error { | |
| if err == nil { | |
| return nil | |
| } | |
| return &withStack{ | |
| err, | |
| callers(), | |
| } | |
| } | |
| type withStack struct { | |
| error | |
| *stack | |
| } | |
| func (w *withStack) Cause() error { return w.error } | |
| // Unwrap provides compatibility for Go 1.13 error chains. | |
| func (w *withStack) Unwrap() error { return w.error } | |
| func (w *withStack) Format(s fmt.State, verb rune) { | |
| switch verb { | |
| case 'v': | |
| if s.Flag('+') { | |
| fmt.Fprintf(s, "%+v", w.Cause()) | |
| w.stack.Format(s, verb) | |
| return | |
| } | |
| fallthrough | |
| case 's': | |
| io.WriteString(s, w.Error()) | |
| case 'q': | |
| fmt.Fprintf(s, "%q", w.Error()) | |
| } | |
| } | |
| // Wrap returns an error annotating err with a stack trace | |
| // at the point Wrap is called, and the supplied message. | |
| // If err is nil, Wrap returns nil. | |
| func Wrap(err error, message string) error { | |
| if err == nil { | |
| return nil | |
| } | |
| err = &withMessage{ | |
| cause: err, | |
| msg: message, | |
| } | |
| return &withStack{ | |
| err, | |
| callers(), | |
| } | |
| } | |
| // Wrapf returns an error annotating err with a stack trace | |
| // at the point Wrapf is called, and the format specifier. | |
| // If err is nil, Wrapf returns nil. | |
| func Wrapf(err error, format string, args ...interface{}) error { | |
| if err == nil { | |
| return nil | |
| } | |
| err = &withMessage{ | |
| cause: err, | |
| msg: fmt.Sprintf(format, args...), | |
| } | |
| return &withStack{ | |
| err, | |
| callers(), | |
| } | |
| } | |
| // WithMessage annotates err with a new message. | |
| // If err is nil, WithMessage returns nil. | |
| func WithMessage(err error, message string) error { | |
| if err == nil { | |
| return nil | |
| } | |
| return &withMessage{ | |
| cause: err, | |
| msg: message, | |
| } | |
| } | |
| // WithMessagef annotates err with the format specifier. | |
| // If err is nil, WithMessagef returns nil. | |
| func WithMessagef(err error, format string, args ...interface{}) error { | |
| if err == nil { | |
| return nil | |
| } | |
| return &withMessage{ | |
| cause: err, | |
| msg: fmt.Sprintf(format, args...), | |
| } | |
| } | |
| type withMessage struct { | |
| cause error | |
| msg string | |
| } | |
| func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } | |
| func (w *withMessage) Cause() error { return w.cause } | |
| // Unwrap provides compatibility for Go 1.13 error chains. | |
| func (w *withMessage) Unwrap() error { return w.cause } | |
| func (w *withMessage) Format(s fmt.State, verb rune) { | |
| switch verb { | |
| case 'v': | |
| if s.Flag('+') { | |
| fmt.Fprintf(s, "%+v\n", w.Cause()) | |
| io.WriteString(s, w.msg) | |
| return | |
| } | |
| fallthrough | |
| case 's', 'q': | |
| io.WriteString(s, w.Error()) | |
| } | |
| } | |
| // Cause returns the underlying cause of the error, if possible. | |
| // An error value has a cause if it implements the following | |
| // interface: | |
| // | |
| // type causer interface { | |
| // Cause() error | |
| // } | |
| // | |
| // If the error does not implement Cause, the original error will | |
| // be returned. If the error is nil, nil will be returned without further | |
| // investigation. | |
| func Cause(err error) error { | |
| type causer interface { | |
| Cause() error | |
| } | |
| for err != nil { | |
| cause, ok := err.(causer) | |
| if !ok { | |
| break | |
| } | |
| err = cause.Cause() | |
| } | |
| return err | |
| } |