This repository has been archived by the owner on Jan 4, 2022. It is now read-only.
/
error.go
168 lines (151 loc) · 4.28 KB
/
error.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
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
156
157
158
159
160
161
162
163
164
165
166
167
168
package mego
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"reflect"
)
type errorMsgs []*Error
// ErrorType 是錯誤種類。
type ErrorType uint64
var (
// ErrEventNotFound 表示欲發送的事件沒有被初始化或任何客戶端監聽而無法找到因此發送失敗。
ErrEventNotFound = errors.New("mego: the event doesn't exist")
// ErrChannelNotFound 表示欲發送的事件存在,但目標頻道沒有被初始化或任何客戶端監聽而無法找到因此發送失敗。
ErrChannelNotFound = errors.New("mego: the channel doesn't exist")
// ErrFileNotFound 表示欲取得的檔案並不存在,可能是客戶端上傳不完整。
ErrFileNotFound = errors.New("mego: the file was not found")
// ErrKeyNotFound 表示欲從鍵值組中取得的鍵名並不存在。
ErrKeyNotFound = errors.New("mego: the key was not found")
// ErrPanicRecovered 表示 Panic 發生了但已回復正常。
ErrPanicRecovered = errors.New("mego: panic recovered")
)
const (
// ErrorTypeBind 是 `Bind` 錯誤。
ErrorTypeBind ErrorType = 1 << 63
// ErrorTypePrivate 是建議僅供開發內部顯示的錯誤。
ErrorTypePrivate ErrorType = 1 << 0
// ErrorTypePublic 是可公開的錯誤。
ErrorTypePublic ErrorType = 1 << 1
// ErrorTypeAny 是任意、不限公開或較私密的錯誤。
ErrorTypeAny ErrorType = 1<<64 - 1
)
// Error 呈現了一個路由中發生的錯誤。
type Error struct {
// Err 是實際的錯誤資料。
Err error
// Meta 是這個錯誤的中繼資料,可傳遞至其他函式讀取運用。
Meta interface{}
// Type 是這個錯誤的種類,預設為 `ErrorTypePrivate`。
Type ErrorType
}
// Error 會回傳一個錯誤的代表訊息。
func (e *Error) Error() string {
return e.Err.Error()
}
// IsType 會表示此錯誤是否為指定的種類。
func (e *Error) IsType(flags ErrorType) bool {
return (e.Type & flags) > 0
}
// SetMeta 可以將自訂的資料保存至錯誤建構體中傳遞到其他地方進行運用。
func (e *Error) SetMeta(data interface{}) *Error {
e.Meta = data
return e
}
func (e *Error) JSON() interface{} {
json := H{}
if e.Meta != nil {
value := reflect.ValueOf(e.Meta)
switch value.Kind() {
case reflect.Struct:
return e.Meta
case reflect.Map:
for _, key := range value.MapKeys() {
json[key.String()] = value.MapIndex(key).Interface()
}
default:
json["meta"] = e.Meta
}
}
if _, ok := json["error"]; !ok {
json["error"] = e.Error()
}
return json
}
// MarshalJSON implements the json.Marshaller interface.
func (e *Error) MarshalJSON() ([]byte, error) {
return json.Marshal(e.JSON())
}
// ByType 回傳一個以指定錯誤種類過濾後的現存錯誤清單。
func (a errorMsgs) ByType(t ErrorType) errorMsgs {
if len(a) == 0 {
return nil
}
if t == ErrorTypeAny {
return a
}
var result errorMsgs
for _, msg := range a {
if msg.IsType(t) {
result = append(result, msg)
}
}
return result
}
// Last 回傳最後發生的一個錯誤,如果沒有錯誤發生則是 `nil`。
// 簡單說這就是 `errors[len(errors)-1]` 的縮寫用法。
func (a errorMsgs) Last() *Error {
if length := len(a); length > 0 {
return a[length-1]
}
return nil
}
// Errors 會回傳一個錯誤訊息切片。
// 舉例來說:
// c.Error(errors.New("一"))
// c.Error(errors.New("二"))
// c.Error(errors.New("三"))
// c.Errors.Errors() // == []string{"一", "二", "三"}
func (a errorMsgs) Errors() []string {
if len(a) == 0 {
return nil
}
errorStrings := make([]string, len(a))
for i, err := range a {
errorStrings[i] = err.Error()
}
return errorStrings
}
//
func (a errorMsgs) JSON() interface{} {
switch len(a) {
case 0:
return nil
case 1:
return a.Last().JSON()
default:
json := make([]interface{}, len(a))
for i, err := range a {
json[i] = err.JSON()
}
return json
}
}
func (a errorMsgs) MarshalJSON() ([]byte, error) {
return json.Marshal(a.JSON())
}
// String 會從錯誤切片輸出成一個可供人類閱讀的錯誤列表字串,其中亦包含所有的中繼資料。
func (a errorMsgs) String() string {
if len(a) == 0 {
return ""
}
var buffer bytes.Buffer
for i, msg := range a {
fmt.Fprintf(&buffer, "Error #%02d: %s\n", i+1, msg.Err)
if msg.Meta != nil {
fmt.Fprintf(&buffer, " Meta: %v\n", msg.Meta)
}
}
return buffer.String()
}