errors.go raw

   1  // Package errors provides simple error handling primitives.
   2  //
   3  // The traditional error handling idiom in Go is roughly akin to
   4  //
   5  //     if err != nil {
   6  //             return err
   7  //     }
   8  //
   9  // which when applied recursively up the call stack results in error reports
  10  // without context or debugging information. The errors package allows
  11  // programmers to add context to the failure path in their code in a way
  12  // that does not destroy the original value of the error.
  13  //
  14  // Adding context to an error
  15  //
  16  // The errors.Wrap function returns a new error that adds context to the
  17  // original error by recording a stack trace at the point Wrap is called,
  18  // together with the supplied message. For example
  19  //
  20  //     _, err := ioutil.ReadAll(r)
  21  //     if err != nil {
  22  //             return errors.Wrap(err, "read failed")
  23  //     }
  24  //
  25  // If additional control is required, the errors.WithStack and
  26  // errors.WithMessage functions destructure errors.Wrap into its component
  27  // operations: annotating an error with a stack trace and with a message,
  28  // respectively.
  29  //
  30  // Retrieving the cause of an error
  31  //
  32  // Using errors.Wrap constructs a stack of errors, adding context to the
  33  // preceding error. Depending on the nature of the error it may be necessary
  34  // to reverse the operation of errors.Wrap to retrieve the original error
  35  // for inspection. Any error value which implements this interface
  36  //
  37  //     type causer interface {
  38  //             Cause() error
  39  //     }
  40  //
  41  // can be inspected by errors.Cause. errors.Cause will recursively retrieve
  42  // the topmost error that does not implement causer, which is assumed to be
  43  // the original cause. For example:
  44  //
  45  //     switch err := errors.Cause(err).(type) {
  46  //     case *MyError:
  47  //             // handle specifically
  48  //     default:
  49  //             // unknown error
  50  //     }
  51  //
  52  // Although the causer interface is not exported by this package, it is
  53  // considered a part of its stable public interface.
  54  //
  55  // Formatted printing of errors
  56  //
  57  // All error values returned from this package implement fmt.Formatter and can
  58  // be formatted by the fmt package. The following verbs are supported:
  59  //
  60  //     %s    print the error. If the error has a Cause it will be
  61  //           printed recursively.
  62  //     %v    see %s
  63  //     %+v   extended format. Each Frame of the error's StackTrace will
  64  //           be printed in detail.
  65  //
  66  // Retrieving the stack trace of an error or wrapper
  67  //
  68  // New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
  69  // invoked. This information can be retrieved with the following interface:
  70  //
  71  //     type stackTracer interface {
  72  //             StackTrace() errors.StackTrace
  73  //     }
  74  //
  75  // The returned errors.StackTrace type is defined as
  76  //
  77  //     type StackTrace []Frame
  78  //
  79  // The Frame type represents a call site in the stack trace. Frame supports
  80  // the fmt.Formatter interface that can be used for printing information about
  81  // the stack trace of this error. For example:
  82  //
  83  //     if err, ok := err.(stackTracer); ok {
  84  //             for _, f := range err.StackTrace() {
  85  //                     fmt.Printf("%+s:%d\n", f, f)
  86  //             }
  87  //     }
  88  //
  89  // Although the stackTracer interface is not exported by this package, it is
  90  // considered a part of its stable public interface.
  91  //
  92  // See the documentation for Frame.Format for more details.
  93  package errors
  94  
  95  import (
  96  	"fmt"
  97  	"io"
  98  )
  99  
 100  // New returns an error with the supplied message.
 101  // New also records the stack trace at the point it was called.
 102  func New(message string) error {
 103  	return &fundamental{
 104  		msg:   message,
 105  		stack: callers(),
 106  	}
 107  }
 108  
 109  // Errorf formats according to a format specifier and returns the string
 110  // as a value that satisfies error.
 111  // Errorf also records the stack trace at the point it was called.
 112  func Errorf(format string, args ...interface{}) error {
 113  	return &fundamental{
 114  		msg:   fmt.Sprintf(format, args...),
 115  		stack: callers(),
 116  	}
 117  }
 118  
 119  // fundamental is an error that has a message and a stack, but no caller.
 120  type fundamental struct {
 121  	msg string
 122  	*stack
 123  }
 124  
 125  func (f *fundamental) Error() string { return f.msg }
 126  
 127  func (f *fundamental) Format(s fmt.State, verb rune) {
 128  	switch verb {
 129  	case 'v':
 130  		if s.Flag('+') {
 131  			io.WriteString(s, f.msg)
 132  			f.stack.Format(s, verb)
 133  			return
 134  		}
 135  		fallthrough
 136  	case 's':
 137  		io.WriteString(s, f.msg)
 138  	case 'q':
 139  		fmt.Fprintf(s, "%q", f.msg)
 140  	}
 141  }
 142  
 143  // WithStack annotates err with a stack trace at the point WithStack was called.
 144  // If err is nil, WithStack returns nil.
 145  func WithStack(err error) error {
 146  	if err == nil {
 147  		return nil
 148  	}
 149  	return &withStack{
 150  		err,
 151  		callers(),
 152  	}
 153  }
 154  
 155  type withStack struct {
 156  	error
 157  	*stack
 158  }
 159  
 160  func (w *withStack) Cause() error { return w.error }
 161  
 162  // Unwrap provides compatibility for Go 1.13 error chains.
 163  func (w *withStack) Unwrap() error { return w.error }
 164  
 165  func (w *withStack) Format(s fmt.State, verb rune) {
 166  	switch verb {
 167  	case 'v':
 168  		if s.Flag('+') {
 169  			fmt.Fprintf(s, "%+v", w.Cause())
 170  			w.stack.Format(s, verb)
 171  			return
 172  		}
 173  		fallthrough
 174  	case 's':
 175  		io.WriteString(s, w.Error())
 176  	case 'q':
 177  		fmt.Fprintf(s, "%q", w.Error())
 178  	}
 179  }
 180  
 181  // Wrap returns an error annotating err with a stack trace
 182  // at the point Wrap is called, and the supplied message.
 183  // If err is nil, Wrap returns nil.
 184  func Wrap(err error, message string) error {
 185  	if err == nil {
 186  		return nil
 187  	}
 188  	err = &withMessage{
 189  		cause: err,
 190  		msg:   message,
 191  	}
 192  	return &withStack{
 193  		err,
 194  		callers(),
 195  	}
 196  }
 197  
 198  // Wrapf returns an error annotating err with a stack trace
 199  // at the point Wrapf is called, and the format specifier.
 200  // If err is nil, Wrapf returns nil.
 201  func Wrapf(err error, format string, args ...interface{}) error {
 202  	if err == nil {
 203  		return nil
 204  	}
 205  	err = &withMessage{
 206  		cause: err,
 207  		msg:   fmt.Sprintf(format, args...),
 208  	}
 209  	return &withStack{
 210  		err,
 211  		callers(),
 212  	}
 213  }
 214  
 215  // WithMessage annotates err with a new message.
 216  // If err is nil, WithMessage returns nil.
 217  func WithMessage(err error, message string) error {
 218  	if err == nil {
 219  		return nil
 220  	}
 221  	return &withMessage{
 222  		cause: err,
 223  		msg:   message,
 224  	}
 225  }
 226  
 227  // WithMessagef annotates err with the format specifier.
 228  // If err is nil, WithMessagef returns nil.
 229  func WithMessagef(err error, format string, args ...interface{}) error {
 230  	if err == nil {
 231  		return nil
 232  	}
 233  	return &withMessage{
 234  		cause: err,
 235  		msg:   fmt.Sprintf(format, args...),
 236  	}
 237  }
 238  
 239  type withMessage struct {
 240  	cause error
 241  	msg   string
 242  }
 243  
 244  func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
 245  func (w *withMessage) Cause() error  { return w.cause }
 246  
 247  // Unwrap provides compatibility for Go 1.13 error chains.
 248  func (w *withMessage) Unwrap() error { return w.cause }
 249  
 250  func (w *withMessage) Format(s fmt.State, verb rune) {
 251  	switch verb {
 252  	case 'v':
 253  		if s.Flag('+') {
 254  			fmt.Fprintf(s, "%+v\n", w.Cause())
 255  			io.WriteString(s, w.msg)
 256  			return
 257  		}
 258  		fallthrough
 259  	case 's', 'q':
 260  		io.WriteString(s, w.Error())
 261  	}
 262  }
 263  
 264  // Cause returns the underlying cause of the error, if possible.
 265  // An error value has a cause if it implements the following
 266  // interface:
 267  //
 268  //     type causer interface {
 269  //            Cause() error
 270  //     }
 271  //
 272  // If the error does not implement Cause, the original error will
 273  // be returned. If the error is nil, nil will be returned without further
 274  // investigation.
 275  func Cause(err error) error {
 276  	type causer interface {
 277  		Cause() error
 278  	}
 279  
 280  	for err != nil {
 281  		cause, ok := err.(causer)
 282  		if !ok {
 283  			break
 284  		}
 285  		err = cause.Cause()
 286  	}
 287  	return err
 288  }
 289