gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

errors.go (7439B)


      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 }