-
Notifications
You must be signed in to change notification settings - Fork 1
/
candy.go
142 lines (122 loc) · 2.26 KB
/
candy.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
package utils
import (
"io"
"runtime/debug"
"github.com/pkg/errors"
)
func Catch(fn any) (isPanic bool, err error) {
defer func() {
r := recover()
if r == nil {
return
}
isPanic = true
switch v := r.(type) {
case error:
err = errors.Wrapf(v, "panic when call Catch function =>\n%s", debug.Stack())
default:
err = errors.Errorf("panic when call Catch function: %s =>\n%s", r, debug.Stack())
}
}()
// check supported function
var v any
switch f := fn.(type) {
case func():
f()
case func() error:
err = f()
case func() (any, error):
v, err = f()
default:
panic(errors.Errorf("unsupported function signature %T", fn))
}
if err != nil {
return
}
if ve, ok := v.(error); ok {
err = ve
}
return
}
func CheckIfAny(fnList ...func() error) error {
for _, fn := range fnList {
if err := fn(); err != nil {
return err
}
}
return nil
}
func IfAny(fnList ...func() bool) {
for _, fn := range fnList {
if fn() {
break
}
}
}
func MustSuccess(err error) {
if err != nil {
panic(err)
}
}
func Must[T any](out T, err error) T {
if err != nil {
panic(err)
}
return out
}
func MustOk[T any](out T, ok bool) T {
if !ok {
panic(errors.Errorf("get %T with ok is false", out))
}
return out
}
type closerA interface{ Close() }
type closerB[T any] interface{ Close() T }
func CloseAnyway[T any](closer T) {
if any(closer) == nil {
return
}
switch c := any(closer).(type) {
case io.Closer:
_ = c.Close()
case closerA:
c.Close()
case closerB[T]:
c.Close()
}
}
type flusherA interface{ Flush() }
type flusherB interface{ Flush() error }
func FlushAnyway[T any](flusher T) {
if any(flusher) == nil {
return
}
switch f := any(flusher).(type) {
case flusherA:
f.Flush()
case flusherB:
_ = f.Flush()
}
}
func ErrIgnore(src error, ignored ...error) (dst error) {
for _, target := range ignored {
if errors.Is(src, target) {
return
}
}
return src
}
type lookupByFuzzyKeywordFuncType[T any] interface {
func(string) T |
func(string) (T, bool) |
func(string) (T, error)
}
func LookupByFuzzyKeyword[T any, F lookupByFuzzyKeywordFuncType[T]](lookup F, keyword string) (v T) {
fn := WrapFunc1[T](lookup)
for _, k := range FuzzyKeyword(keyword) {
if v = fn(k); !IsBlank(v) {
return
}
}
return
}