-
Notifications
You must be signed in to change notification settings - Fork 1
/
util.go
129 lines (114 loc) · 2.64 KB
/
util.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
package gofn
import "reflect"
// If returns the 2nd arg if the condition is true, 3rd arg otherwise
// This is similar to C-language ternary operation (cond ? val1 : val2)
// Deprecated: this function may cause unexpected behavior upon misuses
//
// For example: gofn.If(len(slice) > 0, slice[0], dafaultVal) will crash if slice is empty
func If[C bool, T any](cond C, v1 T, v2 T) T {
if cond {
return v1
}
return v2
}
// Or logically selects the first value which is not zero value of type T
// This function is similar to `FirstTrue`, but it uses generic, not reflection.
func Or[T NumberEx | NumberPtr | StringEx | StringPtr | ~bool | *bool](args ...T) T {
var defaultVal T
for _, v := range args {
if v != defaultVal {
return v
}
}
return defaultVal
}
// FirstTrue returns the first "true" value in the given arguments if found
// True value is not:
// - zero value (0, "", nil, false)
// - empty slice, array, map, channel
// - non-nil pointer points to non-zero value
func FirstTrue[T any](a0 T, args ...T) T {
a := a0
for i := -1; i < len(args); i++ {
if i >= 0 {
a = args[i]
}
if isTrueValue(reflect.ValueOf(a)) {
return a
}
}
return a0
}
func isTrueValue(v reflect.Value) bool {
if !v.IsValid() || v.IsZero() {
return false
}
k := v.Kind()
if k == reflect.Pointer || k == reflect.Interface {
return isTrueValue(v.Elem())
}
if k == reflect.Slice || k == reflect.Array || k == reflect.Map || k == reflect.Chan {
return v.Len() > 0
}
return true
}
func Must1(e error) {
if e != nil {
panic(e)
}
}
func Must2[T any](v T, e error) T {
if e != nil {
panic(e)
}
return v
}
// Must is the same as Must2
func Must[T any](v T, e error) T {
if e != nil {
panic(e)
}
return v
}
func Must3[T1, T2 any](v1 T1, v2 T2, e error) (T1, T2) {
if e != nil {
panic(e)
}
return v1, v2
}
func Must4[T1, T2, T3 any](v1 T1, v2 T2, v3 T3, e error) (T1, T2, T3) {
if e != nil {
panic(e)
}
return v1, v2, v3
}
func Must5[T1, T2, T3, T4 any](v1 T1, v2 T2, v3 T3, v4 T4, e error) (T1, T2, T3, T4) {
if e != nil {
panic(e)
}
return v1, v2, v3, v4
}
func Must6[T1, T2, T3, T4, T5 any](v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, e error) (T1, T2, T3, T4, T5) {
if e != nil {
panic(e)
}
return v1, v2, v3, v4, v5
}
// New returns pointer to the address of the input
// Helpful for unit testing when create a struct that has field requires pointer type
func New[T any](t T) *T {
return &t
}
// Head returns the first argument
func Head[T any](t T, s ...any) T {
return t
}
// Tail returns the last argument
func Tail[T any](t any, s ...any) (T, bool) {
v := t
if len(s) > 0 {
v = s[len(s)-1]
}
ret, ok := v.(T)
return ret, ok
}