-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommon.go
109 lines (95 loc) · 2.1 KB
/
common.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
package candy
import (
"fmt"
"math"
"reflect"
"runtime"
"strings"
"unicode/utf8"
)
// 字符串长度
func StrLen(s string) int {
return utf8.RuneCountInString(s)
}
// 是否为空值
func IsEmpty[E comparable](e E) bool {
var zero E
return zero == e
}
// 除法。保留x位小数。(最后一位不四舍五入)
func Div[T Integer | Float](a, b T, decimals int) float64 {
if b == 0 {
return 0
}
return Round(float64(a)/float64(b), decimals)
}
// 保留x位小数(最后一位不四舍五入)
func Round(n float64, decimals int) float64 {
if decimals < 0 || decimals > 10 {
panic("decimals is out of range")
}
shift := math.Pow(10, float64(decimals))
return math.Trunc(n*shift) / shift
}
// 结构体、结构体指针、结构体切片
func GetTags(v any, tag string) []string {
var tp reflect.Type
if x, ok := v.(reflect.Type); ok {
tp = x
} else {
tp = reflect.TypeOf(v)
}
if tp.Kind() == reflect.Ptr {
tp = tp.Elem()
}
if tp.Kind() == reflect.Slice {
tp = tp.Elem()
}
n := tp.NumField()
result := make([]string, 0, n)
for i := 0; i < n; i++ {
field := tp.Field(i)
s := field.Tag.Get(tag)
if s == "-" {
continue
}
// json:"xxx,omitempty"
if s != "" {
if idx := strings.IndexByte(s, ','); idx > -1 {
s = s[0:idx]
}
}
// 如果有标签则记录,如果没标签,判断是否为嵌套的结构体
if s != "" {
result = append(result, s)
} else if field.Type.Kind() == reflect.Struct {
result = append(result, GetTags(field.Type, tag)...)
}
}
return result
}
// 追踪调用位置
func Callers(skip int) []string {
pc := make([]uintptr, 10)
n := runtime.Callers(skip, pc)
if n == 0 {
return nil
}
callers := make([]string, 0, n)
pc = pc[:n]
for _, p := range pc {
fn := runtime.FuncForPC(p)
if fn == nil {
continue
}
file, line := fn.FileLine(p)
if !strings.Contains(file, "/go/src/") && !strings.Contains(file, "/go/pkg/") {
arr := strings.Split(file, "/")
if len(arr) > 3 {
file = strings.Join(arr[len(arr)-3:], "/")
}
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
}
}
return callers
}