-
Notifications
You must be signed in to change notification settings - Fork 0
/
errorx.go
107 lines (91 loc) · 2.18 KB
/
errorx.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
package errorx
import (
"errors"
"fmt"
"strings"
)
// Newf returns an error according to a format specifier and param.
// Each call to New returns a distinct error value even if the text is identical.
//
// If tracing is enabled then stacktrace is attached to the returned error.
func Newf(format string, a ...any) error {
// NOTE: go vet printf check doesn't understand inverse expression.
if !Tracing() || strings.Contains(format, "%w") {
return fmt.Errorf(format, a...)
}
msg := format
if a != nil {
msg = fmt.Sprintf(format, a...)
}
return &errorString{
s: msg,
frame: caller(1),
}
}
// Is is just [errors.Is].
func Is(err, target error) bool {
return errors.Is(err, target)
}
// As is just [errors.As].
func As(err error, target any) bool {
return errors.As(err, target)
}
// Into is type-safe alternative to [errorx.As].
func Into[T error](err error) (T, bool) {
var dst T
ok := As(err, &dst)
return dst, ok
}
// Unwrap is just [errors.Unwrap].
func Unwrap(err error) error {
return errors.Unwrap(err)
}
// UnwrapMulti is just [errors.Unwrap] for errors created via [errors.Join].
// Returns slice with 1 element if a regular error is passed.
func UnwrapMulti(err error) []error {
// multiError represents error created by [errors.Join].
// There is no way to unwrap it without casting to this interface.
type multiError interface {
Unwrap() []error
}
errs, ok := err.(multiError)
if ok {
return errs.Unwrap()
}
return []error{err}
}
// IsAny is just a multiple [errors.Is] calls.
func IsAny(err, target error, targets ...error) bool {
if errors.Is(err, target) {
return true
}
for _, t := range targets {
if errors.Is(err, t) {
return true
}
}
return false
}
// Must returns value or panic if the error is non-nil.
func Must[T any](v T, err error) T {
if err != nil {
panic(err)
}
return v
}
// errorString same as [errors.errorString] but with a frame field.
type errorString struct {
s string
frame Frame
}
func (e *errorString) Error() string {
return e.s
}
func (e *errorString) Format(s fmt.State, v rune) {
FormatError(e, s, v)
}
func (e *errorString) FormatError(p Printer) (next error) {
p.Print(e.s)
e.frame.Format(p)
return nil
}