Skip to content

Commit 491d8ee

Browse files
committed
Additional features for wrapped try errors.
Add OriginalError convenience accessor. Rename data key var to make more sense. Add package level documentation pointing out CatchAll's error wrapping behavior.
1 parent f313887 commit 491d8ee

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

try/try.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@
3333
(no special treatment; they'll hit `CatchAll` blocks and `Finally` blocks;
3434
it would of course be silly for them to hit `Catch` blocks since those
3535
use spacemonkey-errors types). Panics with values that are not of golang's
36-
`error` type at all will trigger `Finally` blocks but otherwise
37-
be immediately repanicked.
36+
`error` type at all will be wrapped in a spacemonkey error for the purpose
37+
of handling (as an interface design, `CatchAll(interface{})` is unpleasant).
38+
See `OriginalError` and `Repanic` for more invormation on handling these
39+
wrapped panic objects.
3840
3941
A `try.Do(func() {...})` with no attached errors handlers is legal but
4042
pointless. A `try.Do(func() {...})` with no `Done()` will never run the
@@ -61,7 +63,7 @@ var (
6163
UnknownPanicError = errors.NewClass("Unknown Error")
6264

6365
// The spacemonkey error key to get the original data out of an UnknownPanicError.
64-
OriginalPanic = errors.GenSym()
66+
OriginalErrorKey = errors.GenSym()
6567
)
6668

6769
type Plan struct {
@@ -153,14 +155,14 @@ func (p *Plan) Done() {
153155
if catch.match == nil {
154156
consumed = true
155157
msg := fmt.Sprintf("%v", rec)
156-
pan := UnknownPanicError.NewWith(msg, errors.SetData(OriginalPanic, rec))
158+
pan := UnknownPanicError.NewWith(msg, errors.SetData(OriginalErrorKey, rec))
157159
catch.anyhandler(pan)
158160
return
159161
}
160162
if UnknownPanicError.Is(catch.match) {
161163
consumed = true
162164
msg := fmt.Sprintf("%v", rec)
163-
pan := UnknownPanicError.NewWith(msg, errors.SetData(OriginalPanic, rec))
165+
pan := UnknownPanicError.NewWith(msg, errors.SetData(OriginalErrorKey, rec))
164166
catch.handler(pan.(*errors.Error))
165167
return
166168
}
@@ -170,9 +172,26 @@ func (p *Plan) Done() {
170172
p.main()
171173
}
172174

175+
/*
176+
If `err` was originally another value coerced to an error by `CatchAll`,
177+
this will return the original value. Otherwise, it returns the same error
178+
again.
179+
180+
See also `Repanic()`.
181+
*/
182+
func OriginalError(err error) interface{} {
183+
data := errors.GetData(err, OriginalErrorKey)
184+
if data == nil {
185+
return err
186+
}
187+
return data
188+
}
189+
173190
/*
174191
Panics again with the original error.
175192
193+
Shorthand, equivalent to calling `panic(OriginalError(err))`
194+
176195
If the error is a `UnknownPanicError` (i.e., a `CatchAll` block that's handling something
177196
that wasn't originally an `error` type, so it was wrapped), it will unwrap that re-panic
178197
with that original error -- in other words, this is a "do the right thing" method in all scenarios.
@@ -192,9 +211,9 @@ func Repanic(err error) {
192211
if !wrapper.Is(UnknownPanicError) {
193212
panic(err)
194213
}
195-
data := errors.GetData(err, OriginalPanic)
214+
data := errors.GetData(err, OriginalErrorKey)
196215
if data == nil {
197-
panic(errors.ProgrammerError.New("misuse of try internals", errors.SetData(OriginalPanic, err)))
216+
panic(errors.ProgrammerError.New("misuse of try internals", errors.SetData(OriginalErrorKey, err)))
198217
}
199218
panic(data)
200219
}

try/try_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ func ExampleIntOriginalPanic() {
173173
}).Finally(func() {
174174
fmt.Println("finally block called")
175175
}).CatchAll(func(e error) {
176-
data := errors.GetData(e, try.OriginalPanic)
176+
data := errors.GetData(e, try.OriginalErrorKey)
177177
fmt.Println("catch wildcard called:", data)
178178
switch data.(type) {
179179
case int:
@@ -197,7 +197,7 @@ func ExampleCatchingUnknownErrorsByType() {
197197
}).Catch(RockError, func(e *errors.Error) {
198198
fmt.Println("catch a rock")
199199
}).Catch(try.UnknownPanicError, func(e *errors.Error) {
200-
data := errors.GetData(e, try.OriginalPanic)
200+
data := errors.GetData(e, try.OriginalErrorKey)
201201
fmt.Println("catch UnknownPanicError called:", data)
202202
switch data.(type) {
203203
case int:
@@ -276,7 +276,7 @@ func ExampleStringRepanicCoversFinally() {
276276
}).Finally(func() {
277277
fmt.Println("finally block called")
278278
}).Catch(try.UnknownPanicError, func(e *errors.Error) {
279-
data := errors.GetData(e, try.OriginalPanic)
279+
data := errors.GetData(e, try.OriginalErrorKey)
280280
fmt.Println("catch UnknownPanicError called:", data)
281281
switch data.(type) {
282282
case string:
@@ -316,7 +316,7 @@ func ExampleObjectRepanicOriginal() {
316316
}).CatchAll(func(e error) {
317317
// this example is a little funny, because it got re-wrapped again
318318
// but the important part is yes, the (pointer equal!) object is in there.
319-
data := errors.GetData(e, try.OriginalPanic)
319+
data := errors.GetData(e, try.OriginalErrorKey)
320320
fmt.Printf("outer error equals original: %v\n", data == obj)
321321
}).Done()
322322

0 commit comments

Comments
 (0)