| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- // Package errors implements functions for manipulating errors.
- package errors
- import (
- "fmt"
- "io"
- "os"
- "runtime"
- "strings"
- )
- type loc uintptr
- func (l loc) Location() (string, int) {
- pc := uintptr(l)
- fn := runtime.FuncForPC(pc)
- if fn == nil {
- return "unknown", 0
- }
- _, prefix, _, _ := runtime.Caller(0)
- file, line := fn.FileLine(pc)
- if i := strings.LastIndex(prefix, "github.com/pkg/errors"); i > 0 {
- file = file[i:]
- }
- return file, line
- }
- // New returns an error that formats as the given text.
- func New(text string) error {
- pc, _, _, _ := runtime.Caller(1)
- return struct {
- error
- loc
- }{
- fmt.Errorf(text),
- loc(pc),
- }
- }
- type e struct {
- cause error
- message string
- loc
- }
- func (e *e) Error() string {
- return e.message + ": " + e.cause.Error()
- }
- func (e *e) Cause() error {
- return e.cause
- }
- // Wrap returns an error annotating the cause with message.
- // If cause is nil, Wrap returns nil.
- func Wrap(cause error, message string) error {
- if cause == nil {
- return nil
- }
- pc, _, _, _ := runtime.Caller(1)
- return &e{
- cause: cause,
- message: message,
- loc: loc(pc),
- }
- }
- type causer interface {
- Cause() 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 {
- for err != nil {
- cause, ok := err.(causer)
- if !ok {
- break
- }
- err = cause.Cause()
- }
- return err
- }
- type locationer interface {
- Location() (string, int)
- }
- // Print prints the error to Stderr.
- // If the error implements the Causer interface described in Cause
- // Print will recurse into the error's cause.
- // If the error implements the inteface:
- //
- // type Location interface {
- // Location() (file string, line int)
- // }
- //
- // Print will also print the file and line of the error.
- func Print(err error) {
- Fprint(os.Stderr, err)
- }
- // Fprint prints the error to the supplied writer.
- // The format of the output is the same as Print.
- // If err is nil, nothing is printed.
- func Fprint(w io.Writer, err error) {
- for err != nil {
- location, ok := err.(locationer)
- if ok {
- file, line := location.Location()
- fmt.Fprintf(w, "%s:%d: ", file, line)
- }
- switch err := err.(type) {
- case *e:
- fmt.Fprintln(w, err.message)
- default:
- fmt.Fprintln(w, err.Error())
- }
- cause, ok := err.(causer)
- if !ok {
- break
- }
- err = cause.Cause()
- }
- }
|