@@ -18,8 +18,9 @@ import (
18
18
type (
19
19
// we want these to be type aliases, so they are much nicer to use
20
20
PanicHandler = func (p any )
21
- ErrorHandler = func (err error )
22
- NilHandler = func ()
21
+ ErrorHandler = func (err error ) error // this is only proper type that work
22
+ NilHandler = func () error // TODO: we remove this
23
+ CheckHandler = func (noerr bool ) error
23
24
)
24
25
25
26
// Info tells to Process function how to proceed.
@@ -40,43 +41,40 @@ type Info struct {
40
41
// handler then we call still ErrorHandler and get the error from Any. It
41
42
// goes for other way around: we get error but nilHandler is only one to
42
43
// set, we use that for the error (which is accessed from the closure).
43
- NilHandler // If nil default implementation is used.
44
44
ErrorHandler // If nil default implementation is used.
45
+ NilHandler // If nil default (pre-defined here) implementation is used.
45
46
46
47
PanicHandler // If nil panic() is called.
47
48
49
+ CheckHandler // this would be for cases where there isn't any error, but
50
+ // this should be the last defer.
51
+
48
52
CallerName string
53
+
54
+ werr error
49
55
}
50
56
51
57
const (
52
58
wrapError = ": %w"
53
59
)
54
60
55
61
func PanicNoop (_ any ) {}
56
- func NilNoop () { }
62
+ func NilNoop () error { return nil }
57
63
58
64
// func ErrorNoop(err error) {}
59
65
60
66
func (i * Info ) callNilHandler () {
61
- if ! i .workToDo () {
62
- return
63
- }
64
-
65
67
if i .safeErr () != nil {
66
68
i .checkErrorTracer ()
67
69
}
68
70
if i .NilHandler != nil {
69
- i .NilHandler ()
71
+ * i . Err = i .NilHandler ()
70
72
} else {
71
73
i .defaultNilHandler ()
72
74
}
73
75
}
74
76
75
77
func (i * Info ) checkErrorTracer () {
76
- if ! i .workToDo () {
77
- return
78
- }
79
-
80
78
if i .ErrorTracer == nil {
81
79
i .ErrorTracer = tracer .Error .Tracer ()
82
80
}
@@ -90,13 +88,9 @@ func (i *Info) checkErrorTracer() {
90
88
}
91
89
92
90
func (i * Info ) callErrorHandler () {
93
- if ! i .workToDo () {
94
- return
95
- }
96
-
97
91
i .checkErrorTracer ()
98
92
if i .ErrorHandler != nil {
99
- i .ErrorHandler (i .Any .(error ))
93
+ * i . Err = i .ErrorHandler (i .Any .(error ))
100
94
} else {
101
95
i .defaultErrorHandler ()
102
96
}
@@ -113,10 +107,6 @@ func (i *Info) checkPanicTracer() {
113
107
}
114
108
115
109
func (i * Info ) callPanicHandler () {
116
- if ! i .workToDo () {
117
- return
118
- }
119
-
120
110
i .checkPanicTracer ()
121
111
if i .PanicHandler != nil {
122
112
i .PanicHandler (i .Any )
@@ -125,29 +115,52 @@ func (i *Info) callPanicHandler() {
125
115
}
126
116
}
127
117
128
- func (i * Info ) defaultNilHandler ( ) {
129
- err : = i .safeErr ()
118
+ func (i * Info ) workError () ( err error ) {
119
+ err = i .safeErr ()
130
120
if err == nil {
131
121
var ok bool
132
122
err , ok = i .Any .(error )
133
123
if ! ok {
134
- return
124
+ return nil
135
125
}
136
126
}
137
- if err != nil {
138
- if i .Format != "" {
139
- * i .Err = fmt .Errorf (i .Format + i .wrapStr (), append (i .Args , err )... )
140
- } else {
141
- * i .Err = err
142
- }
127
+ return err
128
+ }
129
+
130
+ func (i * Info ) fmtErr () {
131
+ * i .Err = fmt .Errorf (i .Format + i .wrapStr (), append (i .Args , i .werr )... )
132
+ }
133
+
134
+ func (i * Info ) buildFmtErr () {
135
+ if i .Format != "" {
136
+ i .fmtErr ()
137
+ return
138
+ }
139
+ * i .Err = i .werr
140
+ }
141
+
142
+ func (i * Info ) safeCallErrorHandler () {
143
+ if i .ErrorHandler != nil {
144
+ * i .Err = i .ErrorHandler (i .werr )
143
145
}
146
+ }
147
+
148
+ func (i * Info ) defaultNilHandler () {
149
+ i .werr = i .workError ()
150
+ if i .werr == nil {
151
+ return
152
+ }
153
+ i .buildFmtErr ()
144
154
if i .workToDo () {
145
155
// error transported thru i.Err not by panic (i.Any)
146
156
// let's allow caller to use ErrorHandler if it's set
147
- if i .ErrorHandler != nil {
148
- i .ErrorHandler (err )
149
- return
150
- }
157
+ i .safeCallErrorHandler ()
158
+ }
159
+ }
160
+
161
+ func (i * Info ) safeCallNilHandler () {
162
+ if i .NilHandler != nil {
163
+ * i .Err = i .NilHandler ()
151
164
}
152
165
}
153
166
@@ -158,26 +171,15 @@ func (i *Info) defaultNilHandler() {
158
171
// get panic object's error (below). We still must call handler functions to the
159
172
// rest of the handlers if there is an error.
160
173
func (i * Info ) defaultErrorHandler () {
161
- err := i .safeErr ()
162
- if err == nil {
163
- var ok bool
164
- err , ok = i .Any .(error )
165
- if ! ok {
166
- return
167
- }
168
- }
169
- if i .Format != "" {
170
- * i .Err = fmt .Errorf (i .Format + i .wrapStr (), append (i .Args , err )... )
171
- } else {
172
- * i .Err = err
174
+ i .werr = i .workError ()
175
+ if i .werr == nil {
176
+ return
173
177
}
178
+ i .buildFmtErr ()
174
179
if i .workToDo () {
175
180
// error transported thru i.Err not by panic (i.Any)
176
181
// let's allow caller to use NilHandler if it's set
177
- if i .NilHandler != nil {
178
- i .NilHandler ()
179
- return
180
- }
182
+ i .safeCallNilHandler ()
181
183
}
182
184
}
183
185
@@ -215,7 +217,7 @@ func Process(info *Info) {
215
217
switch info .Any .(type ) {
216
218
case nil :
217
219
info .callNilHandler ()
218
- case runtime.Error :
220
+ case runtime.Error : // need own or handled like errors
219
221
info .callPanicHandler ()
220
222
case error :
221
223
info .callErrorHandler ()
@@ -224,12 +226,14 @@ func Process(info *Info) {
224
226
}
225
227
}
226
228
227
- // PreProcess is currently used for err2 API like err2.Handle and .Catch.
228
- //
229
- // - That there is an error or a panic to handle i.e. that's taken care.
230
- //
231
- //nolint:nestif
232
- func PreProcess (info * Info , a ... any ) {
229
+ func PreProcess (er * error , info * Info , a ... any ) error {
230
+ // Bug in Go?
231
+ // start to use local error ptr only for optimization reasons.
232
+ // We get 3x faster defer handlers without unsing ptr to original err
233
+ // named return val. Reason is unknown.
234
+ err := x .Whom (er != nil , * er , nil )
235
+ info .Err = & err
236
+
233
237
// We want the function who sets the handler, i.e. calls the
234
238
// err2.Handle function via defer. Because call stack is in reverse
235
239
// order we need negative, and because the Handle caller is just
@@ -277,6 +281,7 @@ func PreProcess(info *Info, a ...any) {
277
281
* info .Err = nil // prevent dublicate "logging"
278
282
}
279
283
}
284
+ return err
280
285
}
281
286
282
287
func firstArgIsString (a ... any ) bool {
@@ -310,10 +315,13 @@ func processArg(info *Info, i int, a ...any) {
310
315
info .PanicHandler = first
311
316
case NilHandler :
312
317
info .NilHandler = first
318
+ case CheckHandler :
319
+ info .CheckHandler = first
313
320
case nil :
314
- info .NilHandler = NilNoop
321
+ info .NilHandler = NilNoop // TODO: this resets the error!! need
322
+ // argument!!!
315
323
default :
316
- // we don't panic because we can already be in recovery, but lets
324
+ // we don't panic here because we can already be in recovery, but lets
317
325
// try to show an error message at least.
318
326
fmt .Fprintln (os .Stderr , "fatal error: err2.Handle: unsupported type" )
319
327
}
0 commit comments