podman

Форк
0
288 строк · 7.3 Кб
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
}
289

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.