forked from mitranim/try
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtry_defer.go
205 lines (184 loc) · 5.18 KB
/
try_defer.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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package try
import "github.com/pkg/errors"
/*
Must be deferred. Tool for adding a stacktrace to an arbitrary panic. Unlike
the "rec" functions, this does NOT prevent the panic from propagating. It
simply ensures that there's a stacktrace, then re-panics.
Caution: due to idiosyncrasies of `recover()`, this works ONLY when deferred
directly. Anything other than `defer try.Trace()` will NOT work.
*/
func Trace() { To(Err(recover())) }
/*
Must be deferred. Runs the function only if there's no panic. Idempotently adds
a stacktrace.
*/
func Ok(fun func()) {
To(Err(recover()))
fun()
}
/*
Must be deferred. Runs the function ONLY if there's an ongoing panic, and then
re-panics. Idempotently adds a stacktrace.
*/
func Fail(fun func(error)) {
err := Err(recover())
if err != nil && fun != nil {
fun(err)
}
To(err)
}
/*
Must be deferred. Short for "transmute" or "transform". Catches an ongoing
panic, transforms the error by calling the provided function, and then
re-panics via `To`. Can be used to ignore specific errors, by converting them
to nil, which prevents the second panic. Idempotently adds a stacktrace.
*/
func Trans(fun func(error) error) {
err := Err(recover())
if err != nil && fun != nil {
err = fun(err)
}
To(err)
}
/*
Must be deferred. Wraps non-nil panics, prepending the error message and
idempotently adding a stacktrace.
*/
func Detail(msg string) {
To(errors.WithMessage(Err(recover()), msg))
}
/*
Must be deferred. Wraps non-nil panics, prepending the error message and
idempotently adding a stacktrace.
*/
func Detailf(msg string, args ...interface{}) {
To(errors.WithMessagef(Err(recover()), msg, args...))
}
/*
Must be deferred. Wraps non-nil panics, prepending the error message, ONLY if
they satisfy the provided test. Idempotently adds a stacktrace to all panics.
*/
func DetailOnly(test func(error) bool, msg string) {
err := Err(recover())
if err != nil && test != nil && test(err) {
err = errors.WithMessage(err, msg)
}
To(err)
}
/*
Must be deferred. Wraps non-nil panics, prepending the error message, ONLY if
they satisfy the provided test. Idempotently adds a stacktrace to all panics.
*/
func DetailOnlyf(test func(error) bool, msg string, args ...interface{}) {
err := Err(recover())
if err != nil && test != nil && test(err) {
err = errors.WithMessagef(err, msg, args...)
}
To(err)
}
/*
Must be deferred. Catches and ignores ALL panics.
*/
func Ignore() { recover() }
/*
Must be deferred. Catches panics; ignores errors that satisfy the provided
test; re-panics on other non-nil errors. Idempotently adds a stacktrace.
*/
func IgnoreOnly(test func(error) bool) {
err := Err(recover())
if err != nil && test != nil && test(err) {
return
}
To(err)
}
/*
Must be deferred. Recovers from panics, writing the resulting error, if any, to
the given pointer. Should be used together with "try"-style functions.
Idempotently adds a stacktrace.
*/
func Rec(ptr *error) {
err := Err(recover())
if err != nil {
*ptr = err
}
}
/*
Must be deferred. Filtered version of `Rec`. Recovers from panics that satisfy
the provided test. Re-panics on non-nil errors that don't satisfy the test.
Does NOT check errors that are returned normally, without a panic. Should be
used together with "try"-style functions. Idempotently adds a stacktrace.
*/
func RecOnly(ptr *error, test func(error) bool) {
err := Err(recover())
if err != nil {
*ptr = err
if test != nil && test(err) {
return
}
panic(err)
}
}
/*
Must be deferred. Version of `Rec` that sends the recovered error, if any, to
the given channel. Idempotently adds a stacktrace.
*/
func RecChan(errChan chan<- error) {
err := Err(recover())
if err != nil {
select {
case errChan <- err:
default:
}
}
}
/*
Must be deferred. Recovery for background goroutines that have nowhere to return
their error. Unlike the other "rec" functions, this doesn't send the error
anywhere; instead it calls the provided function ONLY if the error was
non-nil.
Functions that CAN return errors should use the other "rec" functions instead.
*/
func RecWith(fun func(error)) {
err := Err(recover())
if err != nil {
fun(err)
}
}
/*
Must be deferred. Combination of `Rec` and `WithMessage`. Recovers from panics
and adds a message. Idempotently adds a stacktrace.
*/
func RecWithMessage(ptr *error, msg string) {
err := Err(recover())
if err != nil {
*ptr = errors.WithMessage(err, msg)
}
}
/*
Must be deferred. Combination of `Rec` and `WithMessagef`. Recovers from panics
and adds a message. Idempotently adds a stacktrace.
*/
func RecWithMessagef(ptr *error, pattern string, args ...interface{}) {
err := Err(recover())
if err != nil {
*ptr = errors.WithMessagef(err, pattern, args...)
}
}
/*
Must be deferred. Wraps a non-nil error, prepending the message. Unlike
`RecWithMessage`, does NOT implicitly recover or add a stacktrace.
*/
func WithMessage(ptr *error, msg string) {
if ptr != nil && *ptr != nil {
*ptr = errors.WithMessage(*ptr, msg)
}
}
/*
Must be deferred. Wraps a non-nil error, prepending the message. Unlike
`RecWithMessagef`, does NOT implicitly recover or add a stacktrace.
*/
func WithMessagef(ptr *error, pattern string, args ...interface{}) {
if ptr != nil && *ptr != nil {
*ptr = errors.WithMessagef(*ptr, pattern, args...)
}
}