Files
structx/structx.go
T
2025-09-21 00:30:53 +08:00

1112 lines
28 KiB
Go
Raw 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 structx
import (
"encoding/json"
"fmt"
"reflect"
"strconv"
"strings"
"code.yun.ink/pkg/convx"
"github.com/spf13/cast"
)
type ChangeInfo struct {
Old string `json:"old"`
New string `json:"new"`
Val interface{} `json:"val"`
}
// 统一的类型转换函数
type converterFunc func(reflect.Value, string) (interface{}, error)
var typeConverters = map[reflect.Kind]converterFunc{
reflect.Bool: convertBool,
reflect.Int: convertInt[int],
reflect.Int8: convertInt[int8],
reflect.Int16: convertInt[int16],
reflect.Int32: convertInt[int32],
reflect.Int64: convertInt[int64],
reflect.Uint: convertUint[uint],
reflect.Uint8: convertUint[uint8],
reflect.Uint16: convertUint[uint16],
reflect.Uint32: convertUint[uint32],
reflect.Uint64: convertUint[uint64],
reflect.Float32: convertFloat[float32],
reflect.Float64: convertFloat[float64],
reflect.String: convertString,
reflect.Slice: convertSlice,
reflect.Array: convertArray,
reflect.Map: convertMap,
}
// 缓存类型信息以避免重复反射操作
var typeInfoCache = make(map[reflect.Type]map[string]fieldInfo)
// AttactToStructAny 将 map[string]interface{} 类型的值附加到结构体中
func AttactToStructAny(structxx interface{}, updateMap map[string]interface{}) (map[string]ChangeInfo, error) {
stringMap := make(map[string]string, len(updateMap))
for k, v := range updateMap {
str, err := cast.ToStringE(v)
if err != nil {
return nil, fmt.Errorf("转换键 %s 的值失败: %w", k, err)
}
stringMap[k] = str
}
return AttactToStruct(structxx, stringMap)
}
// AttactToStruct 将 map 的数据赋值到结构体中,支持嵌套结构体和指针
func AttactToStruct(structxx interface{}, updateMap map[string]string) (map[string]ChangeInfo, error) {
v := reflect.ValueOf(structxx)
if v.Kind() != reflect.Ptr || v.IsNil() {
return nil, fmt.Errorf("structxx 需要是非空指针")
}
changeMap := make(map[string]ChangeInfo)
v = v.Elem()
// 获取结构体类型信息
t := v.Type()
fieldMap := buildFieldMap(t)
for mapKey, mapValue := range updateMap {
fieldInfo, exists := fieldMap[mapKey]
if !exists {
return nil, fmt.Errorf("字段 %s 不存在", mapKey)
}
// 获取字段值,正确处理指针
field := v
for i, idx := range fieldInfo.Index {
// 确保当前字段是结构体类型(不是指针)
if field.Kind() == reflect.Ptr {
if field.IsNil() {
newValue := reflect.New(field.Type().Elem())
field.Set(newValue)
}
field = field.Elem()
}
if field.Kind() != reflect.Struct {
return nil, fmt.Errorf("字段索引 %v 不是结构体类型", fieldInfo.Index[:i+1])
}
field = field.Field(idx)
if !field.IsValid() {
return nil, fmt.Errorf("字段索引 %v 无效", fieldInfo.Index[:i+1])
}
}
// 现在 field 是最终的字段值,可能是指针或非指针
var actualField reflect.Value
if field.Kind() == reflect.Ptr {
if field.IsNil() {
newValue := reflect.New(field.Type().Elem())
field.Set(newValue)
}
actualField = field.Elem()
} else {
actualField = field
}
if !actualField.IsValid() {
continue
}
// 处理切片和数组类型
if fieldInfo.IsSlice || fieldInfo.IsArray {
err := processSliceOrArrayField(actualField, mapValue, mapKey)
if err != nil {
return nil, fmt.Errorf("处理切片/数组字段 %s 失败: %w", mapKey, err)
}
continue
}
// 处理嵌套结构体
if actualField.Kind() == reflect.Struct && !isBasicStructType(actualField.Type()) {
nestedChanges, err := processNestedStruct(actualField, mapValue, mapKey)
if err != nil {
return nil, fmt.Errorf("处理嵌套结构体字段 %s 失败: %w", mapKey, err)
}
for nestedKey, change := range nestedChanges {
changeMap[nestedKey] = change
}
continue
}
if !actualField.CanSet() {
continue
}
// 处理基本类型
oldValueStr, err := cast.ToStringE(actualField.Interface())
if err != nil {
oldValueStr = fmt.Sprintf("%v", actualField.Interface())
}
newValue, err := setFieldValue(actualField, mapValue)
if err != nil {
return nil, fmt.Errorf("设置字段 %s 的值失败: %w", mapKey, err)
}
newValueStr, err := cast.ToStringE(newValue)
if err != nil {
newValueStr = fmt.Sprintf("%v", newValue)
}
changeMap[mapKey] = ChangeInfo{
Old: oldValueStr,
New: newValueStr,
Val: newValue,
}
}
return changeMap, nil
}
// 处理切片和数组字段
func processSliceOrArrayField(field reflect.Value, value string, fieldKey string) error {
// 尝试解析JSON数组
var jsonData []interface{}
if err := json.Unmarshal([]byte(value), &jsonData); err != nil {
return fmt.Errorf("字段 %s 的值必须是JSON数组格式: %w", fieldKey, err)
}
fieldType := field.Type()
elemType := fieldType.Elem()
// 创建新的切片或数组
var newContainer reflect.Value
if fieldType.Kind() == reflect.Slice {
newContainer = reflect.MakeSlice(fieldType, len(jsonData), len(jsonData))
} else if fieldType.Kind() == reflect.Array {
if len(jsonData) != fieldType.Len() {
return fmt.Errorf("字段 %s 的数组长度不匹配: 期望 %d, 实际 %d",
fieldKey, fieldType.Len(), len(jsonData))
}
newContainer = reflect.New(fieldType).Elem()
} else {
return fmt.Errorf("字段 %s 不是切片或数组类型", fieldKey)
}
// 填充数据
for i, item := range jsonData {
elemValue := newContainer.Index(i)
err := setSliceElementValue(elemValue, item, elemType)
if err != nil {
return fmt.Errorf("设置切片/数组元素失败: %w", err)
}
}
field.Set(newContainer)
return nil
}
// 设置切片/数组元素的值
func setSliceElementValue(elemValue reflect.Value, item interface{}, elemType reflect.Type) error {
// 处理指针类型的元素
if elemType.Kind() == reflect.Ptr {
if elemValue.IsNil() {
elemValue.Set(reflect.New(elemType.Elem()))
}
return setSliceElementValue(elemValue.Elem(), item, elemType.Elem())
}
// 检查是否实现了 UnmarshalJSON 方法
if hasUnmarshalJSON(elemType) {
return setUnmarshalJSONValue(elemValue, item)
}
// 根据元素类型进行转换
switch elemType.Kind() {
case reflect.String:
elemValue.SetString(convertToString(item))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
num, err := convertToFloat64(item)
if err != nil {
return fmt.Errorf("无法将 %v 转换为整型: %w", item, err)
}
elemValue.SetInt(int64(num))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
num, err := convertToFloat64(item)
if err != nil {
return fmt.Errorf("无法将 %v 转换为无符号整型: %w", item, err)
}
elemValue.SetUint(uint64(num))
case reflect.Float32, reflect.Float64:
num, err := convertToFloat64(item)
if err != nil {
return fmt.Errorf("无法将 %v 转换为浮点型: %w", item, err)
}
elemValue.SetFloat(num)
case reflect.Bool:
b, ok := item.(bool)
if !ok {
return fmt.Errorf("无法将 %v 转换为布尔型", item)
}
elemValue.SetBool(b)
case reflect.Struct:
if isBasicStructType(elemType) {
return setBasicStructElement(elemValue, item, elemType)
}
return setStructElement(elemValue, item)
default:
return fmt.Errorf("不支持的切片元素类型: %s", elemType.Kind())
}
return nil
}
// 辅助转换函数
func convertToString(item interface{}) string {
if str, ok := item.(string); ok {
return str
}
return fmt.Sprintf("%v", item)
}
func convertToFloat64(item interface{}) (float64, error) {
switch v := item.(type) {
case float64:
return v, nil
case int, int32, int64:
return float64(reflect.ValueOf(v).Int()), nil
case uint, uint32, uint64:
return float64(reflect.ValueOf(v).Uint()), nil
case float32:
return float64(v), nil
default:
return 0, fmt.Errorf("无法转换为数字")
}
}
// 设置结构体元素
func setStructElement(elemValue reflect.Value, item interface{}) error {
jsonBytes, err := json.Marshal(item)
if err != nil {
return err
}
return json.Unmarshal(jsonBytes, elemValue.Addr().Interface())
}
// 设置基本结构体元素
func setBasicStructElement(elemValue reflect.Value, item interface{}, elemType reflect.Type) error {
return setStructElement(elemValue, item)
}
// getFieldByIndexSafe 安全地通过索引路径获取字段,处理嵌套指针
func getFieldByIndexSafe(v reflect.Value, index []int) (reflect.Value, error) {
if len(index) == 0 {
return v, nil
}
field := v.Field(index[0])
if !field.IsValid() {
return reflect.Value{}, fmt.Errorf("字段索引 %d 无效", index[0])
}
// 递归解引用指针
for field.Kind() == reflect.Ptr {
if field.IsNil() {
elemType := field.Type().Elem()
newValue := reflect.New(elemType)
field.Set(newValue)
}
field = field.Elem()
}
if len(index) > 1 {
return getFieldByIndexSafe(field, index[1:])
}
return field, nil
}
// 构建字段映射表
type fieldInfo struct {
Index []int
Name string
IsPtr bool
FieldType reflect.Type
IsSlice bool
IsArray bool
}
func buildFieldMap(t reflect.Type) map[string]fieldInfo {
// 检查缓存
if cached, exists := typeInfoCache[t]; exists {
return cached
}
fieldMap := make(map[string]fieldInfo)
buildFieldMapRecursive(t, []int{}, fieldMap, "")
// 缓存结果
typeInfoCache[t] = fieldMap
return fieldMap
}
func buildFieldMapRecursive(t reflect.Type, index []int, fieldMap map[string]fieldInfo, prefix string) {
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if !field.IsExported() {
continue
}
currentIndex := append(index, i)
jsonTag := getJSONTagName(field)
fullKey := jsonTag
if prefix != "" {
fullKey = prefix + "." + jsonTag
}
fieldType := field.Type
isPtr := fieldType.Kind() == reflect.Ptr
actualType := fieldType
if isPtr {
actualType = fieldType.Elem()
}
// 处理切片和数组类型
if actualType.Kind() == reflect.Slice || actualType.Kind() == reflect.Array {
fieldMap[fullKey] = fieldInfo{
Index: currentIndex,
Name: field.Name,
IsPtr: isPtr,
FieldType: fieldType,
IsSlice: actualType.Kind() == reflect.Slice,
IsArray: actualType.Kind() == reflect.Array,
}
continue
}
// 处理嵌套结构体
if actualType.Kind() == reflect.Struct && !isBasicStructType(actualType) {
buildFieldMapRecursive(actualType, currentIndex, fieldMap, fullKey)
}
fieldMap[fullKey] = fieldInfo{
Index: currentIndex,
Name: field.Name,
IsPtr: isPtr,
FieldType: fieldType,
}
}
}
func getJSONTagName(field reflect.StructField) string {
jsonTag := field.Tag.Get("json")
if jsonTag == "" || jsonTag == "-" {
return field.Name
}
return strings.Split(jsonTag, ",")[0]
}
// 判断是否为基本结构体类型
func isBasicStructType(t reflect.Type) bool {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
// 检查常见的基本结构体类型
switch {
case t.PkgPath() == "time" && t.Name() == "Time":
return true
case t.PkgPath() == "github.com/shopspring/decimal" && t.Name() == "Decimal":
return true
case strings.HasPrefix(t.String(), "sql.Null"):
return true
}
return false
}
// 检查类型是否实现了 UnmarshalJSON 方法
func hasUnmarshalJSON(t reflect.Type) bool {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
unmarshalerType := reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
return t.Implements(unmarshalerType) || reflect.PtrTo(t).Implements(unmarshalerType)
}
// 检查类型是否实现了 UnmarshalText 方法
func hasUnmarshalText(t reflect.Type) bool {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
textUnmarshalerType := reflect.TypeOf((*interface {
UnmarshalText([]byte) error
})(nil)).Elem()
return t.Implements(textUnmarshalerType) || reflect.PtrTo(t).Implements(textUnmarshalerType)
}
// 使用 UnmarshalJSON 方法设置值
func setUnmarshalJSONValue(field reflect.Value, value interface{}) error {
jsonBytes, err := json.Marshal(value)
if err != nil {
return fmt.Errorf("序列化值失败: %w", err)
}
var fieldAddr reflect.Value
if field.CanAddr() {
fieldAddr = field.Addr()
} else {
temp := reflect.New(field.Type())
temp.Elem().Set(field)
fieldAddr = temp
}
if unmarshaler, ok := fieldAddr.Interface().(json.Unmarshaler); ok {
return unmarshaler.UnmarshalJSON(jsonBytes)
}
return fmt.Errorf("类型 %s 未实现 json.Unmarshaler", field.Type())
}
// 使用 UnmarshalText 方法设置值
func setUnmarshalTextValue(field reflect.Value, value string) error {
var fieldAddr reflect.Value
if field.CanAddr() {
fieldAddr = field.Addr()
} else {
temp := reflect.New(field.Type())
temp.Elem().Set(field)
fieldAddr = temp
}
if unmarshaler, ok := fieldAddr.Interface().(interface {
UnmarshalText([]byte) error
}); ok {
return unmarshaler.UnmarshalText([]byte(value))
}
return fmt.Errorf("类型 %s 未实现 UnmarshalText", field.Type())
}
// 处理嵌套结构体
func processNestedStruct(field reflect.Value, value string, parentKey string) (map[string]ChangeInfo, error) {
changeMap := make(map[string]ChangeInfo)
var structValue reflect.Value
if field.Kind() == reflect.Ptr {
if field.IsNil() {
newValue := reflect.New(field.Type().Elem())
field.Set(newValue)
}
structValue = field.Elem()
} else {
structValue = field
}
if !structValue.IsValid() || structValue.Kind() != reflect.Struct {
return nil, fmt.Errorf("无效的结构体字段")
}
// 尝试解析为JSON对象
var nestedMap map[string]interface{}
if err := json.Unmarshal([]byte(value), &nestedMap); err == nil {
stringMap := make(map[string]string, len(nestedMap))
for k, v := range nestedMap {
str, err := cast.ToStringE(v)
if err != nil {
return nil, fmt.Errorf("转换嵌套字段 %s 的值失败: %w", k, err)
}
stringMap[k] = str
}
nestedChanges, err := AttactToStruct(structValue.Addr().Interface(), stringMap)
if err != nil {
return nil, err
}
for key, change := range nestedChanges {
changeMap[parentKey+"."+key] = change
}
return changeMap, nil
}
// 尝试直接设置结构体值
if hasUnmarshalJSON(structValue.Type()) || isBasicStructType(structValue.Type()) {
oldValueStr, _ := cast.ToStringE(field.Interface())
err := setBasicStructValue(structValue, value)
if err != nil {
return nil, fmt.Errorf("设置基本结构体值失败: %w", err)
}
newValueStr, _ := cast.ToStringE(field.Interface())
changeMap[parentKey] = ChangeInfo{
Old: oldValueStr,
New: newValueStr,
Val: structValue.Interface(),
}
return changeMap, nil
}
return nil, fmt.Errorf("嵌套结构体值必须是有效的JSON格式或基本结构体类型")
}
// 设置基本结构体的值
func setBasicStructValue(field reflect.Value, value string) error {
if hasUnmarshalText(field.Type()) {
return setUnmarshalTextValue(field, value)
}
return json.Unmarshal([]byte(value), field.Addr().Interface())
}
// 设置字段值
func setFieldValue(field reflect.Value, value string) (interface{}, error) {
fieldType := field.Type()
// 优先检查接口实现
if hasUnmarshalJSON(fieldType) {
err := setUnmarshalJSONValue(field, value)
if err != nil {
return nil, fmt.Errorf("UnmarshalJSON 失败: %w", err)
}
return field.Interface(), nil
}
if hasUnmarshalText(fieldType) {
err := setUnmarshalTextValue(field, value)
if err != nil {
return nil, fmt.Errorf("UnmarshalText 失败: %w", err)
}
return field.Interface(), nil
}
// 处理指针类型
if fieldType.Kind() == reflect.Ptr {
return setPointerFieldValue(field, value)
}
// 处理类型别名(如 type CustomString string
if isTypeAlias(fieldType) {
return setTypeAliasValue(field, value)
}
// 处理自定义类型(有包路径的结构体类型)
if isCustomStructType(fieldType) {
return setCustomTypeValue(field, value)
}
// 处理基本类型
converter, exists := typeConverters[fieldType.Kind()]
if !exists {
return nil, fmt.Errorf("不支持的类型: %s", fieldType.Kind().String())
}
result, err := converter(field, value)
if err != nil {
return nil, err
}
field.Set(reflect.ValueOf(result))
return result, nil
}
// 设置类型别名的值
func setTypeAliasValue(field reflect.Value, value string) (interface{}, error) {
fieldType := field.Type()
// 获取基础类型
baseType := getBaseTypeFromAlias(fieldType)
if baseType == nil {
return nil, fmt.Errorf("无法获取类型别名的基础类型: %s", fieldType.String())
}
// 使用基础类型的转换器
converter, exists := typeConverters[baseType.Kind()]
if !exists {
return nil, fmt.Errorf("不支持的基础类型: %s", baseType.Kind().String())
}
// 创建基础类型的临时值
baseValue := reflect.New(baseType).Elem()
result, err := converter(baseValue, value)
if err != nil {
return nil, err
}
// 将基础类型值转换为类型别名
convertedValue, err := convertToTypeAlias(fieldType, result)
if err != nil {
return nil, err
}
field.Set(reflect.ValueOf(convertedValue))
return convertedValue, nil
}
// 将基础类型值转换为类型别名
func convertToTypeAlias(aliasType reflect.Type, value interface{}) (interface{}, error) {
// valueType := reflect.TypeOf(value)
// 处理指针类型的类型别名
if aliasType.Kind() == reflect.Ptr {
elemType := aliasType.Elem()
// 创建新的指针实例
newValue := reflect.New(elemType)
elemValue := newValue.Elem()
// 转换值
converted, err := convertValueToType(value, elemType)
if err != nil {
return nil, err
}
elemValue.Set(reflect.ValueOf(converted))
return newValue.Interface(), nil
}
// 处理非指针类型的类型别名
return convertValueToType(value, aliasType)
}
// 将值转换为指定类型
func convertValueToType(value interface{}, targetType reflect.Type) (interface{}, error) {
valueType := reflect.TypeOf(value)
if valueType.AssignableTo(targetType) {
return value, nil
}
if valueType.ConvertibleTo(targetType) {
return reflect.ValueOf(value).Convert(targetType).Interface(), nil
}
return nil, fmt.Errorf("无法将 %v 转换为 %v", valueType, targetType)
}
// 检查是否为自定义结构体类型
func isCustomStructType(t reflect.Type) bool {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
// 排除基本类型
if t.PkgPath() == "" {
return false
}
// 排除已知的基本结构体类型
if isBasicStructType(t) {
return false
}
// 排除类型别名
if isTypeAlias(t) {
return false
}
// 排除接口类型
if t.Kind() == reflect.Interface {
return false
}
// 必须是结构体类型
return t.Kind() == reflect.Struct
}
// 获取类型别名的基础类型
func getBaseTypeFromAlias(aliasType reflect.Type) reflect.Type {
if aliasType.Kind() == reflect.Ptr {
aliasType = aliasType.Elem()
}
// 根据类型别名的种类返回对应的基础类型
switch aliasType.Kind() {
case reflect.String:
return reflect.TypeOf("")
case reflect.Int:
return reflect.TypeOf(int(0))
case reflect.Int8:
return reflect.TypeOf(int8(0))
case reflect.Int16:
return reflect.TypeOf(int16(0))
case reflect.Int32:
return reflect.TypeOf(int32(0))
case reflect.Int64:
return reflect.TypeOf(int64(0))
case reflect.Uint:
return reflect.TypeOf(uint(0))
case reflect.Uint8:
return reflect.TypeOf(uint8(0))
case reflect.Uint16:
return reflect.TypeOf(uint16(0))
case reflect.Uint32:
return reflect.TypeOf(uint32(0))
case reflect.Uint64:
return reflect.TypeOf(uint64(0))
case reflect.Float32:
return reflect.TypeOf(float32(0))
case reflect.Float64:
return reflect.TypeOf(float64(0))
case reflect.Bool:
return reflect.TypeOf(false)
default:
return nil
}
}
// 检测是否为自定义类型
func isCustomType(t reflect.Type) bool {
// 排除基本类型
if t.PkgPath() == "" {
return false
}
// 排除已知的基本结构体类型
if isBasicStructType(t) {
return false
}
// 排除接口类型
if t.Kind() == reflect.Interface {
return false
}
// 排除基础类型的别名
if isBasicTypeAlias(t) {
return false
}
return true
}
// 检查是否为类型别名(如 type CustomString string
func isTypeAlias(t reflect.Type) bool {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
// 类型别名有包路径且是基本类型
basicKinds := map[reflect.Kind]bool{
reflect.String: true,
reflect.Int: true,
reflect.Int8: true,
reflect.Int16: true,
reflect.Int32: true,
reflect.Int64: true,
reflect.Uint: true,
reflect.Uint8: true,
reflect.Uint16: true,
reflect.Uint32: true,
reflect.Uint64: true,
reflect.Float32: true,
reflect.Float64: true,
reflect.Bool: true,
}
return t.PkgPath() != "" && basicKinds[t.Kind()]
}
// 检查是否为基本类型的别名(如 type CustomString string
func isBasicTypeAlias(t reflect.Type) bool {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
// 检查是否为基本类型的别名
basicKinds := map[reflect.Kind]bool{
reflect.String: true,
reflect.Int: true,
reflect.Int8: true,
reflect.Int16: true,
reflect.Int32: true,
reflect.Int64: true,
reflect.Uint: true,
reflect.Uint8: true,
reflect.Uint16: true,
reflect.Uint32: true,
reflect.Uint64: true,
reflect.Float32: true,
reflect.Float64: true,
reflect.Bool: true,
}
return basicKinds[t.Kind()]
}
// 处理自定义类型
func setCustomTypeValue(field reflect.Value, value string) (interface{}, error) {
// 检查是否实现了TextUnmarshaler接口
if hasUnmarshalText(field.Type()) {
err := setUnmarshalTextValue(field, value)
if err != nil {
return nil, err
}
return field.Interface(), nil
}
// 对于其他自定义结构体类型,尝试JSON解析
var jsonData interface{}
if err := json.Unmarshal([]byte(value), &jsonData); err != nil {
return nil, fmt.Errorf("无法解析JSON: %w", err)
}
jsonBytes, err := json.Marshal(jsonData)
if err != nil {
return nil, err
}
if err := json.Unmarshal(jsonBytes, field.Addr().Interface()); err != nil {
return nil, err
}
return field.Interface(), nil
// // 对于其他自定义类型,我们需要获取其基础类型并进行转换
// baseType := getBaseType(field.Type())
// if baseType == nil {
// return nil, fmt.Errorf("不支持的自定义类型: %s", field.Type().String())
// }
// // 创建基础类型的值并进行转换
// baseValue := reflect.New(baseType).Elem()
// // 使用对应的类型转换器
// converter, exists := typeConverters[baseType.Kind()]
// if !exists {
// return nil, fmt.Errorf("不支持的基础类型: %s", baseType.Kind().String())
// }
// result, err := converter(baseValue, value)
// if err != nil {
// return nil, err
// }
// // 将基础类型值转换回自定义类型
// convertedValue, err := convertToCustomType(field.Type(), result)
// if err != nil {
// return nil, err
// }
// field.Set(reflect.ValueOf(convertedValue))
// return convertedValue, nil
}
// 将基础类型值转换为自定义类型
func convertToCustomType(customType reflect.Type, value interface{}) (interface{}, error) {
valueType := reflect.TypeOf(value)
// 处理指针类型的自定义类型
if customType.Kind() == reflect.Ptr {
elemType := customType.Elem()
// 创建新的指针实例
newValue := reflect.New(elemType)
elemValue := newValue.Elem()
// 尝试将值设置到元素
if valueType.AssignableTo(elemType) {
elemValue.Set(reflect.ValueOf(value))
} else if reflect.ValueOf(value).Type().ConvertibleTo(elemType) {
converted := reflect.ValueOf(value).Convert(elemType)
elemValue.Set(converted)
} else {
// 对于自定义类型,尝试通过字符串转换
if str, ok := value.(string); ok && elemType.Kind() == reflect.String {
elemValue.SetString(str)
} else {
return nil, fmt.Errorf("无法将 %v 转换为 %v", valueType, elemType)
}
}
return newValue.Interface(), nil
}
// 处理非指针类型的自定义类型
if valueType.AssignableTo(customType) {
return value, nil
}
if reflect.ValueOf(value).Type().ConvertibleTo(customType) {
return reflect.ValueOf(value).Convert(customType).Interface(), nil
}
// 对于字符串到自定义字符串类型的转换
if str, ok := value.(string); ok && customType.Kind() == reflect.String {
return reflect.ValueOf(str).Convert(customType).Interface(), nil
}
return nil, fmt.Errorf("无法将 %v 转换为 %v", valueType, customType)
}
// 获取自定义类型的基础类型
func getBaseType(t reflect.Type) reflect.Type {
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
// 如果是自定义类型(有包路径),获取其底层类型
if t.PkgPath() != "" {
// 对于类型别名,我们需要获取其底层的基本类型
switch t.Kind() {
case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64, reflect.Bool:
// 这是基本类型的别名,返回对应的基本类型
switch t.Kind() {
case reflect.String:
return reflect.TypeOf("")
case reflect.Int:
return reflect.TypeOf(int(0))
case reflect.Int8:
return reflect.TypeOf(int8(0))
case reflect.Int16:
return reflect.TypeOf(int16(0))
case reflect.Int32:
return reflect.TypeOf(int32(0))
case reflect.Int64:
return reflect.TypeOf(int64(0))
case reflect.Uint:
return reflect.TypeOf(uint(0))
case reflect.Uint8:
return reflect.TypeOf(uint8(0))
case reflect.Uint16:
return reflect.TypeOf(uint16(0))
case reflect.Uint32:
return reflect.TypeOf(uint32(0))
case reflect.Uint64:
return reflect.TypeOf(uint64(0))
case reflect.Float32:
return reflect.TypeOf(float32(0))
case reflect.Float64:
return reflect.TypeOf(float64(0))
case reflect.Bool:
return reflect.TypeOf(false)
}
default:
// 对于其他自定义类型,尝试获取其底层类型
if t.Kind() == reflect.Struct {
// 如果是结构体,检查是否有可转换的基础类型
if field := getBaseTypeField(t); field.Name != "" {
return field.Type
}
}
}
}
return nil
}
// 获取结构体中可能的基础类型字段
func getBaseTypeField(t reflect.Type) reflect.StructField {
if t.Kind() != reflect.Struct || t.NumField() != 1 {
return reflect.StructField{}
}
field := t.Field(0)
basicKinds := map[reflect.Kind]bool{
reflect.String: true,
reflect.Int: true,
reflect.Int8: true,
reflect.Int16: true,
reflect.Int32: true,
reflect.Int64: true,
reflect.Uint: true,
reflect.Uint8: true,
reflect.Uint16: true,
reflect.Uint32: true,
reflect.Uint64: true,
reflect.Float32: true,
reflect.Float64: true,
reflect.Bool: true,
}
if basicKinds[field.Type.Kind()] && field.IsExported() {
return field
}
return reflect.StructField{}
}
// 处理指针类型的字段
func setPointerFieldValue(field reflect.Value, value string) (interface{}, error) {
if field.Kind() != reflect.Ptr {
return nil, fmt.Errorf("setPointerFieldValue: 期望指针类型,得到 %s", field.Kind())
}
if field.IsNil() {
elemType := field.Type().Elem()
newValue := reflect.New(elemType)
field.Set(newValue)
}
return setFieldValue(field.Elem(), value)
}
// 类型转换函数(保持不变)
func convertBool(field reflect.Value, value string) (interface{}, error) {
return convx.ToBool(value)
}
func convertInt[T int | int8 | int16 | int32 | int64](field reflect.Value, value string) (interface{}, error) {
bits := field.Type().Bits()
intVal, err := strconv.ParseInt(value, 10, bits)
if err != nil {
return nil, err
}
return T(intVal), nil
}
func convertUint[T uint | uint8 | uint16 | uint32 | uint64](field reflect.Value, value string) (interface{}, error) {
bits := field.Type().Bits()
uintVal, err := strconv.ParseUint(value, 10, bits)
if err != nil {
return nil, err
}
return T(uintVal), nil
}
func convertFloat[T float32 | float64](field reflect.Value, value string) (interface{}, error) {
bits := field.Type().Bits()
floatVal, err := strconv.ParseFloat(value, bits)
if err != nil {
return nil, err
}
return T(floatVal), nil
}
func convertString(field reflect.Value, value string) (interface{}, error) {
return value, nil
}
func convertSlice(field reflect.Value, value string) (interface{}, error) {
var result []interface{}
if err := json.Unmarshal([]byte(value), &result); err != nil {
return nil, err
}
return result, nil
}
func convertArray(field reflect.Value, value string) (interface{}, error) {
var result []interface{}
if err := json.Unmarshal([]byte(value), &result); err != nil {
return nil, err
}
return result, nil
}
func convertMap(field reflect.Value, value string) (interface{}, error) {
return nil, fmt.Errorf("map转换未实现")
}