tdengine-mapper-go/scan.go

140 lines
3.5 KiB
Go
Raw Normal View History

2024-09-14 15:57:03 +08:00
package tdmap
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{
2024-09-18 16:51:30 +08:00
UniqueTypeName: uniqueTypeName,
DBName2IndexCache: make(map[string][]int, t.NumField()),
Field2IndexCache: make(map[string][]int, t.NumField()),
Filed2DBNameCache: 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
}
2024-09-18 16:51:30 +08:00
for k, v := range subResult.DBName2IndexCache {
sr.DBName2IndexCache[k] = append(sr.DBName2IndexCache[k], i)
sr.DBName2IndexCache[k] = append(sr.DBName2IndexCache[k], v...)
}
2024-09-18 16:51:30 +08:00
for k, v := range subResult.Field2IndexCache {
sr.Field2IndexCache[k] = append(sr.Field2IndexCache[k], i)
sr.Field2IndexCache[k] = append(sr.Field2IndexCache[k], v...)
}
for k, v := range subResult.Filed2DBNameCache {
sr.Filed2DBNameCache[k] = v
}
2024-09-18 16:51:30 +08:00
sr.DBAnnotatedNames = append(sr.DBAnnotatedNames, subResult.DBAnnotatedNames...)
sr.TaggedFieldNames = append(sr.TaggedFieldNames, subResult.TaggedFieldNames...)
continue
}
// 检查字段是否有db注解
columnName := field.Tag.Get("db")
if columnName == "-" || columnName == "" {
continue
}
2024-09-18 16:51:30 +08:00
sr.Field2IndexCache[field.Name] = append(sr.Field2IndexCache[field.Name], i)
sr.DBName2IndexCache[columnName] = append(sr.DBName2IndexCache[columnName], i)
sr.Filed2DBNameCache[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
}
2024-09-18 16:51:30 +08:00
func getReflectTypeAndValue(data any) (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 ""
}