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