-
Notifications
You must be signed in to change notification settings - Fork 9
/
errors.go
110 lines (100 loc) · 2.54 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
// Package errors provides wrapped errors with stack trace.
package errors
import (
"bytes"
"fmt"
"io"
)
// baseError defines an error that includes a stack trace.
type baseError struct {
cause error // cause is the nested error, building an error chain
code int // code is the error code
msg string // msg is the error description
stack *StackTrace // stack is the error stack, if the error chain already has a stack, it will not be set again
}
// Error implements the Error interface to print the error chain information.
func (b *baseError) Error() string {
var buffer bytes.Buffer
if b.code != 0 {
buffer.WriteString(fmt.Sprintf("%d", b.code))
}
if b.msg != "" {
if buffer.Len() > 0 {
buffer.WriteString(", ")
}
buffer.WriteString(b.msg)
}
if b.cause != nil {
if buffer.Len() > 0 {
buffer.WriteString(GetCfg().ErrorConnectionFlag)
}
buffer.WriteString(b.Cause().Error())
}
return buffer.String()
}
// Format implements the Format interface for printing.
func (b *baseError) Format(s fmt.State, verb rune) {
var stackTrace *StackTrace
defer func() {
if stackTrace != nil {
stackTrace.Format(s, verb)
}
}()
var buffer bytes.Buffer
switch verb {
case 'v':
if s.Flag('+') {
if b.code != 0 {
buffer.WriteString(fmt.Sprintf("%d", b.code))
}
if b.msg != "" {
if buffer.Len() > 0 {
buffer.WriteString(", ")
}
buffer.WriteString(b.msg)
}
if b.cause != nil {
if buffer.Len() > 0 {
buffer.WriteString(GetCfg().ErrorConnectionFlag)
}
buffer.WriteString(fmt.Sprintf("%+v", b.Cause()))
}
_, _ = io.WriteString(s, buffer.String())
if b.stack != nil {
stackTrace = b.stack
}
return
}
fallthrough
case 's':
_, _ = io.WriteString(s, b.Error())
case 'q':
_, _ = fmt.Fprintf(s, "%q", b.Error())
default:
_, _ = fmt.Fprintf(s, "unsupported format: %%!%c, use %%s: %s", verb, b.Error())
}
}
// StackTrace returns the error chain stack trace.
// The deepest error created will carry the stack information and shallow errors will not repeat the record.
func (b *baseError) StackTrace() StackTrace {
e := b
for e != nil {
if e.stack != nil {
break
}
e, _ = e.Cause().(*baseError)
}
return *e.stack
}
// Code returns the code.
func (b *baseError) Code() int {
return b.code
}
// Msg returns the message.
func (b *baseError) Msg() string {
return b.msg
}
// Cause returns the nested error.
func (b *baseError) Cause() error { return b.cause }
// Unwrap supports Go 1.13+ error chains.
func (b *baseError) Unwrap() error { return b.cause }