2
2
package errors
3
3
4
4
import (
5
+ "fmt"
6
+ "io"
5
7
"net/http"
6
8
"runtime"
7
9
"strings"
@@ -62,24 +64,41 @@ type Error struct {
62
64
func (e * Error ) Error () string {
63
65
if e .original != nil {
64
66
// string concatenation with + is ~100x faster than fmt.Sprintf()
65
- return e .fileLine + " " + e .original .Error ()
66
- /*
67
- // use the following code instead of the above return, to avoid nested filename:line
68
- err, _ := e.original.(*Error)
69
- if err != nil {
70
- return err.Error()
67
+ return e .fileLine + ": " + e .message + "\n " + e .original .Error ()
68
+ }
69
+
70
+ if e .message != "" {
71
+ // string concatenation with + is ~100x faster than fmt.Sprintf()
72
+ return e .fileLine + ": " + e .message
73
+ }
74
+
75
+ // string concatenation with + is ~100x faster than fmt.Sprintf()
76
+ return e .fileLine + ": " + DefaultMessage
77
+ }
78
+
79
+ // ErrorWithoutFileLine prints the final string without the stack trace / file+line number
80
+ func (e * Error ) ErrorWithoutFileLine () string {
81
+ if e .original != nil {
82
+ if e .message != "" {
83
+ // string concatenation with + is ~100x faster than fmt.Sprintf()
84
+ msg := e .message + ": "
85
+ if o , ok := e .original .(* Error ); ok {
86
+ msg += o .ErrorWithoutFileLine ()
87
+ } else {
88
+ msg += e .original .Error ()
71
89
}
72
- return fmt.Sprintf("%s %s", e.fileLine, e.original.Error())
73
- */
90
+ return msg
91
+ }
92
+ return e .original .Error ()
74
93
}
75
94
76
95
if e .message != "" {
77
96
// string concatenation with + is ~100x faster than fmt.Sprintf()
78
- return e .fileLine + " " + e . message
97
+ return e .message
79
98
}
80
99
81
100
// string concatenation with + is ~100x faster than fmt.Sprintf()
82
- return e .fileLine + " " + DefaultMessage
101
+ return e .fileLine
83
102
}
84
103
85
104
// Message returns the user friendly message stored in the error struct. It will ignore all errors
@@ -101,7 +120,7 @@ func (e *Error) Message() string {
101
120
}
102
121
103
122
if len (messages ) > 0 {
104
- return strings .Join (messages , ". " )
123
+ return strings .Join (messages , ": " )
105
124
}
106
125
107
126
return e .Error ()
@@ -173,6 +192,37 @@ func (e *Error) Type() errType {
173
192
return e .eType
174
193
}
175
194
195
+ // Format implements the verbs supported by Error to be used in fmt annotated/formatted strings
196
+ /*
197
+ %v - the same output as Message(). i.e. recursively get all the custom messages set by user
198
+ - if any of the wrapped error is not of type *Error, that will *not* be displayed
199
+ %+v - recursively prints all the messages along with the file & line number. Also includes output of `Error()` of
200
+ non *Error types.
201
+
202
+ %s - identical to %v
203
+ %+s - recursively prints all the messages without file & line number. Also includes output `Error()` of
204
+ non *Error types.
205
+ */
206
+
207
+ func (e * Error ) Format (s fmt.State , verb rune ) {
208
+ switch verb {
209
+ case 'v' :
210
+ if s .Flag ('+' ) {
211
+ io .WriteString (s , e .Error ())
212
+ } else {
213
+ io .WriteString (s , e .Message ())
214
+ }
215
+ case 's' :
216
+ {
217
+ if s .Flag ('+' ) {
218
+ io .WriteString (s , e .ErrorWithoutFileLine ())
219
+ } else {
220
+ io .WriteString (s , e .Message ())
221
+ }
222
+ }
223
+ }
224
+ }
225
+
176
226
// New returns a new instance of Error with the relavant fields initialized
177
227
func New (msg string ) * Error {
178
228
_ , file , line , _ := runtime .Caller (1 )
0 commit comments