tdengine-mapper-go/scan.go
2024-09-14 16:02:22 +08:00

157 lines
3.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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{
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 ""
}