forked from pkg/errors
-
Notifications
You must be signed in to change notification settings - Fork 0
/
errors.go
136 lines (121 loc) · 2.59 KB
/
errors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// 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()
}
}