Skip to content

Commit f295249

Browse files
lysucoocood
authored andcommitted
make tidb adaptor in errors. (#2)
1 parent 816c908 commit f295249

File tree

7 files changed

+407
-82
lines changed

7 files changed

+407
-82
lines changed

errors.go

Lines changed: 96 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -64,30 +64,22 @@
6464
//
6565
// Retrieving the stack trace of an error or wrapper
6666
//
67-
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
68-
// invoked. This information can be retrieved with the following interface.
69-
//
70-
// type stackTracer interface {
71-
// StackTrace() errors.StackTrace
72-
// }
73-
//
74-
// Where errors.StackTrace is defined as
67+
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are invoked.
68+
// This information can be retrieved with the StackTracer interface that returns
69+
// a StackTrace. Where errors.StackTrace is defined as
7570
//
7671
// type StackTrace []Frame
7772
//
7873
// The Frame type represents a call site in the stack trace. Frame supports
7974
// the fmt.Formatter interface that can be used for printing information about
8075
// the stack trace of this error. For example:
8176
//
82-
// if err, ok := err.(stackTracer); ok {
83-
// for _, f := range err.StackTrace() {
77+
// if stacked := errors.GetStackTracer(err); stacked != nil {
78+
// for _, f := range stacked.StackTrace() {
8479
// fmt.Printf("%+s:%d", f)
8580
// }
8681
// }
8782
//
88-
// stackTracer interface is not exported by this package, but is considered a part
89-
// of stable public API.
90-
//
9183
// See the documentation for Frame.Format for more details.
9284
package errors
9385

@@ -115,6 +107,21 @@ func Errorf(format string, args ...interface{}) error {
115107
}
116108
}
117109

110+
// StackTraceAware is an optimization to avoid repetitive traversals of an error chain.
111+
// HasStack checks for this marker first.
112+
// Annotate/Wrap and Annotatef/Wrapf will produce this marker.
113+
type StackTraceAware interface {
114+
HasStack() bool
115+
}
116+
117+
// HasStack tells whether a StackTracer exists in the error chain
118+
func HasStack(err error) bool {
119+
if errWithStack, ok := err.(StackTraceAware); ok {
120+
return errWithStack.HasStack()
121+
}
122+
return GetStackTracer(err) != nil
123+
}
124+
118125
// fundamental is an error that has a message and a stack, but no caller.
119126
type fundamental struct {
120127
msg string
@@ -145,12 +152,38 @@ func WithStack(err error) error {
145152
if err == nil {
146153
return nil
147154
}
155+
148156
return &withStack{
149157
err,
150158
callers(),
151159
}
152160
}
153161

162+
// AddStack is similar to WithStack.
163+
// However, it will first check with HasStack to see if a stack trace already exists in the causer chain before creating another one.
164+
func AddStack(err error) error {
165+
if HasStack(err) {
166+
return err
167+
}
168+
return WithStack(err)
169+
}
170+
171+
// GetStackTracer will return the first StackTracer in the causer chain.
172+
// This function is used by AddStack to avoid creating redundant stack traces.
173+
//
174+
// You can also use the StackTracer interface on the returned error to get the stack trace.
175+
func GetStackTracer(origErr error) StackTracer {
176+
var stacked StackTracer
177+
WalkDeep(origErr, func(err error) bool {
178+
if stackTracer, ok := err.(StackTracer); ok {
179+
stacked = stackTracer
180+
return true
181+
}
182+
return false
183+
})
184+
return stacked
185+
}
186+
154187
type withStack struct {
155188
error
156189
*stack
@@ -175,15 +208,19 @@ func (w *withStack) Format(s fmt.State, verb rune) {
175208
}
176209

177210
// Wrap returns an error annotating err with a stack trace
178-
// at the point Wrap is called, and the supplied message.
179-
// If err is nil, Wrap returns nil.
211+
// at the point Annotate is called, and the supplied message.
212+
// If err is nil, Annotate returns nil.
213+
//
214+
// Deprecated: use Annotate instead
180215
func Wrap(err error, message string) error {
181216
if err == nil {
182217
return nil
183218
}
219+
hasStack := HasStack(err)
184220
err = &withMessage{
185-
cause: err,
186-
msg: message,
221+
cause: err,
222+
msg: message,
223+
causeHasStack: hasStack,
187224
}
188225
return &withStack{
189226
err,
@@ -192,15 +229,19 @@ func Wrap(err error, message string) error {
192229
}
193230

194231
// Wrapf returns an error annotating err with a stack trace
195-
// at the point Wrapf is call, and the format specifier.
196-
// If err is nil, Wrapf returns nil.
232+
// at the point Annotatef is call, and the format specifier.
233+
// If err is nil, Annotatef returns nil.
234+
//
235+
// Deprecated: use Annotatef instead
197236
func Wrapf(err error, format string, args ...interface{}) error {
198237
if err == nil {
199238
return nil
200239
}
240+
hasStack := HasStack(err)
201241
err = &withMessage{
202-
cause: err,
203-
msg: fmt.Sprintf(format, args...),
242+
cause: err,
243+
msg: fmt.Sprintf(format, args...),
244+
causeHasStack: hasStack,
204245
}
205246
return &withStack{
206247
err,
@@ -215,18 +256,21 @@ func WithMessage(err error, message string) error {
215256
return nil
216257
}
217258
return &withMessage{
218-
cause: err,
219-
msg: message,
259+
cause: err,
260+
msg: message,
261+
causeHasStack: HasStack(err),
220262
}
221263
}
222264

223265
type withMessage struct {
224-
cause error
225-
msg string
266+
cause error
267+
msg string
268+
causeHasStack bool
226269
}
227270

228-
func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
229-
func (w *withMessage) Cause() error { return w.cause }
271+
func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
272+
func (w *withMessage) Cause() error { return w.cause }
273+
func (w *withMessage) HasStack() bool { return w.causeHasStack }
230274

231275
func (w *withMessage) Format(s fmt.State, verb rune) {
232276
switch verb {
@@ -254,16 +298,34 @@ func (w *withMessage) Format(s fmt.State, verb rune) {
254298
// be returned. If the error is nil, nil will be returned without further
255299
// investigation.
256300
func Cause(err error) error {
301+
cause := Unwrap(err)
302+
if cause == nil {
303+
return err
304+
}
305+
return Cause(cause)
306+
}
307+
308+
// Unwrap uses causer to return the next error in the chain or nil.
309+
// This goes one-level deeper, whereas Cause goes as far as possible
310+
func Unwrap(err error) error {
257311
type causer interface {
258312
Cause() error
259313
}
314+
if unErr, ok := err.(causer); ok {
315+
return unErr.Cause()
316+
}
317+
return nil
318+
}
260319

261-
for err != nil {
262-
cause, ok := err.(causer)
263-
if !ok {
264-
break
320+
// Find an error in the chain that matches a test function
321+
func Find(origErr error, test func(error) bool) error {
322+
var foundErr error
323+
WalkDeep(origErr, func(err error) bool {
324+
if test(err) {
325+
foundErr = err
326+
return true
265327
}
266-
err = cause.Cause()
267-
}
268-
return err
328+
return false
329+
})
330+
return foundErr
269331
}

0 commit comments

Comments
 (0)