-
Notifications
You must be signed in to change notification settings - Fork 48
/
errors.go
120 lines (105 loc) · 2.36 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
package errors
import (
"fmt"
"strings"
)
// Interfaces for common error unwrapping.
type causer interface{ Cause() error }
type wrapper interface{ Unwrap() error }
// Cause returns the underlying cause for this error, if possible.
// If err does not implement causer.Cause(), then err is returned.
//
// Deprecated: Use errors.Unwrap, errors.Is or errors.As instead.
func Cause(err error) error {
for err != nil {
if c, ok := err.(wrapper); ok {
err = c.Unwrap()
} else if c, ok := err.(causer); ok {
err = c.Cause()
} else {
return err
}
}
return err
}
// Wrapf wraps an error with a message. Wrapf returns nil if error is nil.
func Wrapf(err error, format string, a ...interface{}) error {
if err == nil {
return nil
}
return &wrapped{
err: err,
msg: fmt.Sprintf(format, a...),
}
}
type wrapped struct {
err error
msg string
}
var (
_ error = (*wrapped)(nil)
_ causer = (*wrapped)(nil)
_ wrapper = (*wrapped)(nil)
)
func (e *wrapped) Error() string { return fmt.Sprintf("%s: %s", e.msg, e.err.Error()) }
func (e *wrapped) Cause() error { return e.err }
func (e *wrapped) Unwrap() error { return e.err }
// Merge errors into one, nil errors are discarded
// and returns nil if all errors are nil.
func Merge(err ...error) error {
var errs []error
for _, e := range err {
if e != nil {
errs = append(errs, e)
}
}
if len(errs) == 0 {
return nil
}
return &merged{s: errs}
}
type merged struct {
s []error
}
var (
_ error = (*merged)(nil)
_ causer = (*merged)(nil)
_ wrapper = (*merged)(nil)
)
func (e *merged) Error() string {
var s strings.Builder
for i, err := range e.s {
if i > 0 {
s.WriteString(": ")
}
s.WriteString(err.Error())
}
return s.String()
}
// Unwrap returns only the first error, there is
// no way to create a queue of errors.
func (e *merged) Unwrap() error { return e.s[0] }
// Cause returns only the first error as there is
// no way to create a queue of errors.
func (e *merged) Cause() error { return e.s[0] }
// Is does errors.Is on all merged errors.
func (e *merged) Is(target error) bool {
if target == nil {
return nil == e.s
}
for _, err := range e.s {
if Is(err, target) {
return true
}
}
return false
}
// As does errors.As on all merged errors.
func (e *merged) As(target interface{}) bool {
for _, err := range e.s {
if As(err, target) {
return true
}
}
return false
}