-
Notifications
You must be signed in to change notification settings - Fork 3
/
convert.go
186 lines (167 loc) · 4.14 KB
/
convert.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package sql
import (
"fmt"
"reflect"
"strconv"
"strings"
"time"
"github.com/abulo/ratel/v3/stores/null"
)
// 转换成string
func toString(src any) (dst string, err error) {
inf := reflect.Indirect(reflect.ValueOf(src)).Interface()
if inf == nil {
return "", nil
}
switch v := inf.(type) {
case string:
dst = v
return
case []byte:
dst = string(v)
return
}
val := reflect.ValueOf(inf)
typ := reflect.TypeOf(inf)
switch typ.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
dst = strconv.FormatInt(val.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
dst = strconv.FormatUint(val.Uint(), 10)
case reflect.Float32, reflect.Float64:
dst = strconv.FormatFloat(val.Float(), 'f', -1, 64)
case reflect.Bool:
dst = strconv.FormatBool(val.Bool())
case reflect.Complex64, reflect.Complex128:
dst = fmt.Sprintf("%v", val.Complex())
case reflect.Struct:
//time.Time
var timeType time.Time
if typ.ConvertibleTo(reflect.TypeOf(timeType)) {
dst = val.Convert(reflect.TypeOf(timeType)).Interface().(time.Time).Format(time.RFC3339Nano)
} else {
err = fmt.Errorf("unsupported struct type %v", val.Type())
}
default:
err = fmt.Errorf("unsupported struct type %v", val.Type())
}
return
}
// 提取tag信息
func extractTagInfo(st reflect.Value) (tagList map[string]reflect.Value, err error) {
stVal := reflect.Indirect(st)
if stVal.Kind() != reflect.Struct {
return nil, fmt.Errorf("the variable type is %v, not a struct", stVal.Kind())
}
tagList = make(map[string]reflect.Value)
for i := 0; i < stVal.NumField(); i++ {
//获取结构体成员
v := stVal.Field(i)
if v.Kind() == reflect.Ptr {
//如果没有初始化,则需要先初始化
if v.IsNil() {
var typ reflect.Type
if v.Type().Kind() == reflect.Ptr {
typ = v.Type().Elem()
} else {
typ = v.Type()
}
vv := reflect.New(typ)
v.Set(vv)
}
//如果是结构体指针,则在进行提取
if v.Elem().Kind() == reflect.Struct {
t, err := extractTagInfo(v.Elem())
if err != nil {
return nil, err
}
for k, ptr := range t {
if _, ok := tagList[k]; ok {
return nil, fmt.Errorf("%s:%s is exists", "db", k)
}
tagList[k] = ptr
}
}
} else if v.Kind() == reflect.Map && v.IsNil() {
//如果是map类型,并且没有初始化,则需要初始化一下
v.Set(reflect.MakeMap(v.Type()))
} else if v.Kind() == reflect.Struct {
var ignore bool
//以下的类型,会再scan的执行转换,所以不需要二次处理
switch v.Interface().(type) {
case time.Time:
ignore = true
case null.Bool:
ignore = true
case null.Byte:
ignore = true
case null.Bytes:
ignore = true
case null.CTime:
ignore = true
case null.Date:
ignore = true
case null.DateTime:
ignore = true
case null.Float32:
ignore = true
case null.Float64:
ignore = true
case null.Int:
ignore = true
case null.Int8:
ignore = true
case null.Int16:
ignore = true
case null.Int32:
ignore = true
case null.Int64:
ignore = true
case null.JSON:
ignore = true
case null.String:
ignore = true
case null.Time:
ignore = true
case null.TimeStamp:
ignore = true
case null.Uint:
ignore = true
case null.Uint8:
ignore = true
case null.Uint16:
ignore = true
case null.Uint32:
ignore = true
case null.Uint64:
ignore = true
}
if !ignore {
t, err := extractTagInfo(v)
if err != nil {
return nil, err
}
for k, ptr := range t {
if _, ok := tagList[k]; ok {
return nil, fmt.Errorf("%s:%s is exists", "db", k)
}
tagList[k] = ptr
}
}
}
tagName := stVal.Type().Field(i).Tag.Get("db")
// tag := stVal.Type().Field(i).Tag.Get("db")
// attrList := strings.Split(tag, ",")
if tagName != "" {
//tag内容通过";"进行分割
attr := strings.Split(tagName, ",")
column := attr[0]
if _, ok := tagList[column]; ok {
return nil, fmt.Errorf("%s:%s is exists", "db", tagName)
}
//字段对应结构体成员地址
tagList[column] = v
}
}
return
}