-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunc.go
More file actions
155 lines (142 loc) · 3.71 KB
/
Copy pathfunc.go
File metadata and controls
155 lines (142 loc) · 3.71 KB
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package xerror
import (
"fmt"
"strconv"
"github.com/gomooth/xerror/xcode"
)
// New 创建纯消息错误,错误码为 CodeNone,httpStatus 默认 500。
func New(message string) XError {
code := xcode.NewMessage(message)
xe := &xError{
errorBase: errorBase{
code: code,
stack: captureStack(1),
chainMsg: message,
errStr: newErrStr(code, message),
},
}
return xe
}
// NewCode 使用错误码创建错误,从注册表继承 httpStatus。
func NewCode(code int, message string) XError {
xc := xcode.NewFromRegistry(code, message)
xe := &xError{
errorBase: errorBase{
code: xc,
stack: captureStack(1),
chainMsg: message,
errStr: newErrStr(xc, message),
},
}
return xe
}
// NewCodef 使用错误码创建格式化错误,从注册表继承 httpStatus。
func NewCodef(code int, format string, args ...any) XError {
return NewCode(code, fmt.Sprintf(format, args...))
}
// NewXCode 使用 XCode 创建错误。可选 message 覆盖 XCode 自身消息。
func NewXCode(code xcode.XCode, message ...string) XError {
if code == nil {
code = xcode.InternalServerError
}
var chainMsg string
if len(message) > 0 && message[0] != "" {
code = xcode.WithMessage(code, message[0])
chainMsg = message[0]
} else {
chainMsg = code.String()
}
return &xError{
errorBase: errorBase{
code: code,
stack: captureStack(1),
chainMsg: chainMsg,
errStr: newErrStr(code, chainMsg),
},
}
}
// NewXCodef 使用 XCode 创建格式化错误。
func NewXCodef(code xcode.XCode, format string, args ...any) XError {
return NewXCode(code, fmt.Sprintf(format, args...))
}
// ParsePayload 提取错误的结构化字段。若 err 不是 XError 或无字段,返回 nil。
func ParsePayload(err error) map[string]any {
if xe, ok := asXErrorInternal(err); ok {
fields := fieldsOf(xe)
if len(fields) > 0 {
return fieldsToMap(fields)
}
}
return nil
}
// StackTrace 返回错误的调用栈文本,不含错误消息。
func StackTrace(err error) string {
if xe, ok := asXErrorInternal(err); ok {
switch e := xe.(type) {
case *xError:
if e.stack != nil {
return e.stack.String()
}
case *xJoinedError:
if e.stack != nil {
return e.stack.String()
}
}
}
return ""
}
// FormatMsg 格式化错误消息内容
func FormatMsg(err error) string {
if xe, ok := asXErrorInternal(err); ok {
buf := make([]byte, 0, 64)
buf = append(buf, '[')
buf = strconv.AppendInt(buf, int64(xe.ErrorCode()), 10)
buf = append(buf, ']', ' ')
buf = append(buf, xe.Message()...)
fields := fieldsOf(xe)
if len(fields) > 0 {
buf = append(buf, ' ')
for i, f := range fields {
if i > 0 {
buf = append(buf, ',', ' ')
}
buf = append(buf, f.Key...)
buf = append(buf, '=')
buf = appendFieldValue(buf, f.Value)
}
}
return string(buf)
}
return err.Error()
}
// appendFieldValue 格式化 Field.Value,对常见类型走快速路径避免反射
func appendFieldValue(buf []byte, v any) []byte {
switch val := v.(type) {
case string:
buf = append(buf, val...)
case int:
buf = strconv.AppendInt(buf, int64(val), 10)
case int64:
buf = strconv.AppendInt(buf, val, 10)
case int32:
buf = strconv.AppendInt(buf, int64(val), 10)
case float64:
buf = strconv.AppendFloat(buf, val, 'f', -1, 64)
case float32:
buf = strconv.AppendFloat(buf, float64(val), 'f', -1, 32)
case bool:
buf = strconv.AppendBool(buf, val)
case nil:
buf = append(buf, "null"...)
default:
buf = append(buf, fmt.Sprintf("%v", val)...)
}
return buf
}
// FormatPayloadFields 格式化 fields 为可读字符串
func FormatPayloadFields(fields []Field) string {
if bs, err := marshalFields(fields); err == nil {
return string(bs)
}
return fmt.Sprintf("%v", fields)
}