-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathpanic.go
More file actions
64 lines (56 loc) · 1.61 KB
/
panic.go
File metadata and controls
64 lines (56 loc) · 1.61 KB
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
package xerrors
import (
"fmt"
)
// PanicError represents an error that occurs during a panic. It is
// returned by the [Recover] and [FromRecover] functions. It provides
// access to the original panic value via the [Panic] method.
//
// Use the standard [errors.As] function to convert an error to this interface.
type PanicError interface {
error
// Panic returns the raw panic value.
Panic() any
}
// Recover wraps the built-in `recover()` function, converting the
// recovered value into an error with a stack trace. The provided `fn`
// callback is only invoked when a panic occurs.
//
// This function must always be used directly with the `defer`
// keyword.
func Recover(fn func(err error)) {
if r := recover(); r != nil {
fn(&withStackTrace{
err: &panicError{panic: r},
stack: callers(2),
})
}
}
// FromRecover converts the result of the built-in `recover()` into
// an error with a stack trace. The returned error implements
// [PanicError]. Returns nil if `r` is nil.
//
// This function must be called in the same function as `recover()`
// to ensure the stack trace is accurate.
func FromRecover(r any) error {
if r == nil {
return nil
}
return &withStackTrace{
err: &panicError{panic: r},
stack: callers(3),
}
}
// panicError represents an error that occurs during a panic,
// constructed from the value returned by `recover()`.
type panicError struct {
panic any
}
// Panic implements the [PanicError] interface.
func (e *panicError) Panic() any {
return e.panic
}
// Error implements the [error] interface.
func (e *panicError) Error() string {
return fmt.Sprintf("panic: %v", e.panic)
}