2024-09-14 15:57:03 +08:00
|
|
|
|
package tdmap
|
2024-09-14 13:12:52 +08:00
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"reflect"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func scan(data interface{}) (*StructMate, error) {
|
|
|
|
|
// 获取结构体的类型
|
|
|
|
|
t, v := getReflectTypeAndValue(data)
|
|
|
|
|
|
|
|
|
|
// 确保是结构体类型
|
|
|
|
|
if t.Kind() != reflect.Struct {
|
|
|
|
|
return nil, fmt.Errorf("input data is not a struct")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取包路径和类型名称
|
|
|
|
|
uniqueTypeName := getUniqueTypeName(t)
|
|
|
|
|
|
|
|
|
|
// 初始化结果结构体
|
|
|
|
|
sr := StructMate{
|
|
|
|
|
UniqueTypeName: uniqueTypeName,
|
|
|
|
|
FieldIndexCache: make(map[string][]int, t.NumField()),
|
|
|
|
|
FiledDBNameCache: make(map[string]string, t.NumField()),
|
|
|
|
|
DBAnnotatedNames: make([]string, 0, t.NumField()),
|
|
|
|
|
TaggedFieldNames: make([]string, 0, t.NumField()),
|
|
|
|
|
SuperTableName: "",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//timeType := reflect.TypeOf(time.Time{})
|
|
|
|
|
|
|
|
|
|
// 遍历结构体的字段
|
|
|
|
|
for i := 0; i < t.NumField(); i++ {
|
|
|
|
|
field := t.Field(i)
|
|
|
|
|
fieldValue := v.Field(i)
|
|
|
|
|
|
|
|
|
|
if field.Anonymous {
|
|
|
|
|
|
|
|
|
|
if field.Type.Kind() == reflect.Ptr {
|
|
|
|
|
if fieldValue.IsNil() {
|
|
|
|
|
// 如果指针是 nil,创建一个该类型的零值实例
|
|
|
|
|
zeroValue := reflect.Zero(field.Type.Elem())
|
|
|
|
|
fieldValue = zeroValue
|
|
|
|
|
} else {
|
|
|
|
|
fieldValue = fieldValue.Elem()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !fieldValue.CanInterface() {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
subResult, err := scan(fieldValue.Interface())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for k, v := range subResult.FieldIndexCache {
|
|
|
|
|
sr.FieldIndexCache[k] = append(sr.FieldIndexCache[k], i)
|
|
|
|
|
sr.FieldIndexCache[k] = append(sr.FieldIndexCache[k], v...)
|
|
|
|
|
}
|
|
|
|
|
for k, v := range subResult.FiledDBNameCache {
|
|
|
|
|
sr.FiledDBNameCache[k] = v
|
|
|
|
|
}
|
|
|
|
|
sr.DBAnnotatedNames = append(sr.DBAnnotatedNames, subResult.DBAnnotatedNames...)
|
|
|
|
|
sr.TaggedFieldNames = append(sr.TaggedFieldNames, subResult.TaggedFieldNames...)
|
|
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// 如果字段是结构体或结构体指针,递归处理
|
|
|
|
|
//if (field.Type.Kind() == reflect.Struct || field.Type.Kind() == reflect.Ptr) && field.Type != timeType {
|
|
|
|
|
//
|
|
|
|
|
// if field.Type.Kind() == reflect.Ptr {
|
|
|
|
|
// if fieldValue.IsNil() {
|
|
|
|
|
// // 如果指针是 nil,创建一个该类型的零值实例
|
|
|
|
|
// zeroValue := reflect.Zero(field.Type.Elem())
|
|
|
|
|
// fieldValue = zeroValue
|
|
|
|
|
// } else {
|
|
|
|
|
// fieldValue = fieldValue.Elem()
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// if !fieldValue.CanInterface() {
|
|
|
|
|
// continue
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// subResult, err := scan(fieldValue.Interface())
|
|
|
|
|
// if err != nil {
|
|
|
|
|
// return nil, err
|
|
|
|
|
// }
|
|
|
|
|
// sr.merge(subResult)
|
|
|
|
|
// continue
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
// 检查字段是否有db注解
|
|
|
|
|
columnName := field.Tag.Get("db")
|
|
|
|
|
if columnName == "-" || columnName == "" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sr.FieldIndexCache[field.Name] = []int{i}
|
|
|
|
|
sr.FiledDBNameCache[field.Name] = columnName
|
|
|
|
|
|
|
|
|
|
// 检查字段是否有taos注解
|
|
|
|
|
if field.Tag.Get("taos") == "tag" {
|
|
|
|
|
sr.TaggedFieldNames = append(sr.TaggedFieldNames, field.Name)
|
|
|
|
|
} else {
|
|
|
|
|
sr.DBAnnotatedNames = append(sr.DBAnnotatedNames, field.Name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sr.SuperTableName = callSuperTableName(data)
|
|
|
|
|
return &sr, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取包路径和类型名称
|
|
|
|
|
func getUniqueTypeName(t reflect.Type) string {
|
|
|
|
|
pkgPath := t.PkgPath()
|
|
|
|
|
typeName := t.Name()
|
|
|
|
|
uniqueTypeName := fmt.Sprintf("%s.%s", pkgPath, typeName)
|
|
|
|
|
return uniqueTypeName
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getReflectTypeAndValue(data interface{}) (reflect.Type, reflect.Value) {
|
|
|
|
|
t := reflect.TypeOf(data)
|
|
|
|
|
v := reflect.ValueOf(data)
|
|
|
|
|
|
|
|
|
|
// 处理结构体和结构体指针
|
|
|
|
|
for t.Kind() == reflect.Ptr {
|
|
|
|
|
t = t.Elem()
|
|
|
|
|
v = v.Elem()
|
|
|
|
|
}
|
|
|
|
|
return t, v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func callSuperTableName(obj any) string {
|
|
|
|
|
v := reflect.ValueOf(obj)
|
|
|
|
|
|
|
|
|
|
if v.Kind() == reflect.Struct {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查是否可以调用 SuperTableName 方法
|
|
|
|
|
superTableNameMethod := v.MethodByName("SuperTableName")
|
|
|
|
|
if !superTableNameMethod.IsValid() {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 调用 SuperTableName 方法
|
|
|
|
|
results := superTableNameMethod.Call(nil)
|
|
|
|
|
if len(results) == 1 && results[0].Kind() == reflect.String {
|
|
|
|
|
return results[0].String()
|
|
|
|
|
}
|
|
|
|
|
return ""
|
|
|
|
|
}
|