22package errors
33
44import (
5+ "fmt"
6+ "io"
57 "net/http"
68 "runtime"
79 "strings"
@@ -62,24 +64,41 @@ type Error struct {
6264func (e * Error ) Error () string {
6365 if e .original != nil {
6466 // 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 ()
7189 }
72- return fmt.Sprintf("%s %s", e.fileLine, e.original.Error())
73- */
90+ return msg
91+ }
92+ return e .original .Error ()
7493 }
7594
7695 if e .message != "" {
7796 // string concatenation with + is ~100x faster than fmt.Sprintf()
78- return e .fileLine + " " + e . message
97+ return e .message
7998 }
8099
81100 // string concatenation with + is ~100x faster than fmt.Sprintf()
82- return e .fileLine + " " + DefaultMessage
101+ return e .fileLine
83102}
84103
85104// 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 {
101120 }
102121
103122 if len (messages ) > 0 {
104- return strings .Join (messages , ". " )
123+ return strings .Join (messages , ": " )
105124 }
106125
107126 return e .Error ()
@@ -173,6 +192,37 @@ func (e *Error) Type() errType {
173192 return e .eType
174193}
175194
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+
176226// New returns a new instance of Error with the relavant fields initialized
177227func New (msg string ) * Error {
178228 _ , file , line , _ := runtime .Caller (1 )
0 commit comments