修改结构体的转换
This commit is contained in:
+476
-150
@@ -1,12 +1,14 @@
|
||||
package structx
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.yun.ink/pkg/convx"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type ChangeInfo struct {
|
||||
@@ -15,170 +17,494 @@ type ChangeInfo struct {
|
||||
Val interface{} `json:"val"`
|
||||
}
|
||||
|
||||
// map[string]interface类型的值附加到结构体中
|
||||
func AttactToStructAny(structxx interface{}, updateMap map[string]interface{}) (map[string]ChangeInfo, error) {
|
||||
m := map[string]string{}
|
||||
for k, v := range updateMap {
|
||||
str, err := convx.ToString(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m[k] = str
|
||||
}
|
||||
// 统一的类型转换函数
|
||||
type converterFunc func(reflect.Value, string) (interface{}, error)
|
||||
|
||||
// fmt.Println("bef", m, structxx)
|
||||
|
||||
r, err := AttactToStruct(structxx, m)
|
||||
// fmt.Println("resp:", r, m, structxx)
|
||||
return r, err
|
||||
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,
|
||||
}
|
||||
|
||||
// 这个方法将map的数据赋值到结构体中
|
||||
// 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) {
|
||||
// 将结构体指针转换为reflect.Value类型
|
||||
v := reflect.ValueOf(structxx)
|
||||
// 如果v不是指针或者v是零值,直接返回
|
||||
if v.Kind() != reflect.Ptr || v.IsNil() {
|
||||
return nil, fmt.Errorf("structxx 需要是指针")
|
||||
return nil, fmt.Errorf("structxx 需要是非空指针")
|
||||
}
|
||||
|
||||
changeMap := make(map[string]ChangeInfo)
|
||||
|
||||
// 获取v指向的元素,也就是结构体本身
|
||||
v = v.Elem()
|
||||
// 遍历map的键和值
|
||||
for k, val := range updateMap {
|
||||
// 根据json标签获取结构体中对应的字段
|
||||
field := v.FieldByNameFunc(func(name string) bool {
|
||||
f, _ := v.Type().FieldByName(name)
|
||||
// fmt.Printf("FieldByNameFunc:%+v\n", f)
|
||||
js := f.Tag.Get("json")
|
||||
s := strings.Split(js, ",")
|
||||
if len(s) > 1 {
|
||||
return s[0] == k
|
||||
|
||||
// 获取结构体类型信息
|
||||
t := v.Type()
|
||||
fieldMap := buildFieldMap(t)
|
||||
|
||||
for mapKey, mapValue := range updateMap {
|
||||
fieldInfo, exists := fieldMap[mapKey]
|
||||
if !exists {
|
||||
continue // 忽略不存在的字段
|
||||
}
|
||||
|
||||
// 安全获取字段值,处理嵌套指针
|
||||
field, err := getFieldByIndexSafe(v, fieldInfo.Index)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取字段 %s 失败: %w", mapKey, err)
|
||||
}
|
||||
|
||||
if !field.IsValid() {
|
||||
continue
|
||||
}
|
||||
|
||||
// 处理指针类型
|
||||
if fieldInfo.IsPtr {
|
||||
if field.IsNil() {
|
||||
// 创建新的指针实例
|
||||
newValue := reflect.New(fieldInfo.FieldType.Elem())
|
||||
field.Set(newValue)
|
||||
}
|
||||
return js == k
|
||||
})
|
||||
// 如果字段存在且可写
|
||||
if field.IsValid() && field.CanSet() {
|
||||
// 根据字段的类型进行类型转换和赋值
|
||||
switch field.Kind() {
|
||||
case reflect.Bool:
|
||||
oldb := field.Bool()
|
||||
olds, _ := convx.ToString(oldb)
|
||||
field = field.Elem()
|
||||
}
|
||||
|
||||
b, _ := convx.ToBool(val)
|
||||
field.SetBool(b)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: b}
|
||||
case reflect.Int64:
|
||||
// 将字符串转换为int64
|
||||
oldi := field.Int()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := strconv.ParseInt(val, 10, 64)
|
||||
field.SetInt(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
case reflect.String:
|
||||
olds := field.String()
|
||||
|
||||
field.SetString(val)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: val}
|
||||
case reflect.Int:
|
||||
oldi := field.Int()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := convx.ToInt64(val)
|
||||
field.SetInt(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
case reflect.Int32:
|
||||
oldi := field.Int()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := convx.ToInt64(val)
|
||||
field.SetInt(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
case reflect.Int16:
|
||||
oldi := field.Int()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := convx.ToInt64(val)
|
||||
field.SetInt(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
case reflect.Int8:
|
||||
oldi := field.Int()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := convx.ToInt64(val)
|
||||
field.SetInt(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
case reflect.Uint:
|
||||
oldi := field.Uint()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := convx.ToInt64(val)
|
||||
field.SetInt(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
case reflect.Uint32:
|
||||
oldi := field.Uint()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := convx.ToInt64(val)
|
||||
field.SetInt(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
case reflect.Uint16:
|
||||
oldi := field.Uint()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := convx.ToInt64(val)
|
||||
field.SetInt(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
case reflect.Uint8:
|
||||
oldi := field.Uint()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := convx.ToInt64(val)
|
||||
field.SetInt(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
case reflect.Uint64:
|
||||
oldi := field.Uint()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := convx.ToInt64(val)
|
||||
field.SetInt(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
case reflect.Float32:
|
||||
oldi := field.Float()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := convx.ToFloat64(val)
|
||||
field.SetFloat(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
case reflect.Float64:
|
||||
oldi := field.Float()
|
||||
olds, _ := convx.ToString(oldi)
|
||||
|
||||
i, _ := convx.ToFloat64(val)
|
||||
field.SetFloat(i)
|
||||
|
||||
changeMap[k] = ChangeInfo{Old: olds, New: val, Val: i}
|
||||
default:
|
||||
fmt.Println("未知类型")
|
||||
return nil, fmt.Errorf("未知类型:" + k)
|
||||
// 处理嵌套结构体(包括指针解引用后的结构体)
|
||||
if field.Kind() == reflect.Struct && !isBasicStructType(field.Type()) {
|
||||
nestedChanges, err := processNestedStruct(field, mapValue, mapKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("处理嵌套结构体字段 %s 失败: %w", mapKey, err)
|
||||
}
|
||||
for nestedKey, change := range nestedChanges {
|
||||
changeMap[nestedKey] = change
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if !field.CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
// 处理基本类型
|
||||
oldValueStr, err := cast.ToStringE(field.Interface())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取字段 %s 的旧值失败: %w", mapKey, err)
|
||||
}
|
||||
|
||||
newValue, err := setFieldValue(field, 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
func buildFieldMap(t reflect.Type) map[string]fieldInfo {
|
||||
fieldMap := make(map[string]fieldInfo)
|
||||
buildFieldMapRecursive(t, []int{}, 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.Struct && !isBasicStructType(actualType) {
|
||||
// 对于指针或非指针的结构体都进行递归展开
|
||||
buildFieldMapRecursive(actualType, currentIndex, fieldMap, fullKey)
|
||||
|
||||
// 同时记录当前字段的信息
|
||||
fieldMap[fullKey] = fieldInfo{
|
||||
Index: currentIndex,
|
||||
Name: field.Name,
|
||||
IsPtr: isPtr,
|
||||
FieldType: fieldType,
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
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]
|
||||
}
|
||||
|
||||
// 判断是否为基本结构体类型(如time.Time等)
|
||||
func isBasicStructType(t reflect.Type) bool {
|
||||
// 处理指针类型
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
|
||||
// 这里可以添加更多需要排除的基本结构体类型
|
||||
if t.PkgPath() == "time" && t.Name() == "Time" {
|
||||
return true
|
||||
}
|
||||
|
||||
// 其他常见的基本结构体类型
|
||||
switch t.String() {
|
||||
case "time.Time", "sql.NullString", "sql.NullInt64", "sql.NullBool", "sql.NullFloat64":
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 处理嵌套结构体(支持JSON解析)
|
||||
// processNestedStruct 处理嵌套结构体
|
||||
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字符串到map
|
||||
var nestedMap map[string]string
|
||||
if err := json.Unmarshal([]byte(value), &nestedMap); err != nil {
|
||||
return nil, fmt.Errorf("嵌套结构体值必须是JSON格式: %w", err)
|
||||
}
|
||||
|
||||
// 递归处理嵌套结构体
|
||||
nestedChanges, err := AttactToStruct(structValue.Addr().Interface(), nestedMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 为嵌套字段的变更记录添加前缀
|
||||
for key, change := range nestedChanges {
|
||||
fullKey := parentKey + "." + key
|
||||
changeMap[fullKey] = change
|
||||
}
|
||||
|
||||
return changeMap, nil
|
||||
}
|
||||
|
||||
// 检测是否为自定义类型
|
||||
func isCustomType(t reflect.Type) bool {
|
||||
// 排除基本类型
|
||||
if t.PkgPath() == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// 排除已知的基本结构体类型
|
||||
if isBasicStructType(t) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 排除接口类型
|
||||
if t.Kind() == reflect.Interface {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 设置字段值
|
||||
// 设置字段值
|
||||
func setFieldValue(field reflect.Value, value string) (interface{}, error) {
|
||||
kind := field.Kind()
|
||||
|
||||
// 检测是否为自定义类型(有包路径的类型)
|
||||
if isCustomType(field.Type()) {
|
||||
return setCustomTypeValue(field, value)
|
||||
}
|
||||
|
||||
// 处理指针类型的基础类型
|
||||
if kind == reflect.Ptr {
|
||||
return setPointerFieldValue(field, value)
|
||||
}
|
||||
|
||||
converter, exists := typeConverters[kind]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("不支持的类型: %s", kind.String())
|
||||
}
|
||||
|
||||
result, err := converter(field, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
field.Set(reflect.ValueOf(result))
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// 处理指针类型的字段
|
||||
func setPointerFieldValue(field reflect.Value, value string) (interface{}, error) {
|
||||
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) {
|
||||
// 实现切片转换逻辑
|
||||
// elemType := field.Type().Elem()
|
||||
// 根据元素类型进行解析
|
||||
return nil, fmt.Errorf("切片转换未实现")
|
||||
}
|
||||
|
||||
func convertArray(field reflect.Value, value string) (interface{}, error) {
|
||||
// 实现数组转换逻辑
|
||||
return nil, fmt.Errorf("数组转换未实现")
|
||||
}
|
||||
|
||||
func convertMap(field reflect.Value, value string) (interface{}, error) {
|
||||
// 实现map转换逻辑
|
||||
return nil, fmt.Errorf("map转换未实现")
|
||||
}
|
||||
|
||||
// 处理自定义类型
|
||||
// 处理自定义类型
|
||||
func setCustomTypeValue(field reflect.Value, value string) (interface{}, error) {
|
||||
// 检查是否实现了TextUnmarshaler接口
|
||||
if unmarshaler, ok := field.Addr().Interface().(interface {
|
||||
UnmarshalText([]byte) error
|
||||
}); ok {
|
||||
err := unmarshaler.UnmarshalText([]byte(value))
|
||||
if 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 getBaseType(t reflect.Type) reflect.Type {
|
||||
for t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
|
||||
// 如果是自定义类型(有包路径),获取其底层类型
|
||||
if t.PkgPath() != "" {
|
||||
return t
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// 将基础类型值转换为自定义类型
|
||||
func convertToCustomType(customType reflect.Type, value interface{}) (interface{}, error) {
|
||||
valueType := reflect.TypeOf(value)
|
||||
customBaseType := customType
|
||||
|
||||
// 处理指针类型的自定义类型
|
||||
if customType.Kind() == reflect.Ptr {
|
||||
customBaseType = customType.Elem()
|
||||
// 创建新的指针实例
|
||||
newValue := reflect.New(customBaseType)
|
||||
elemValue := newValue.Elem()
|
||||
|
||||
// 尝试将值设置到元素
|
||||
if valueType.AssignableTo(customBaseType) {
|
||||
elemValue.Set(reflect.ValueOf(value))
|
||||
} else if reflect.ValueOf(value).Type().ConvertibleTo(customBaseType) {
|
||||
converted := reflect.ValueOf(value).Convert(customBaseType)
|
||||
elemValue.Set(converted)
|
||||
} else {
|
||||
return nil, fmt.Errorf("无法将 %v 转换为 %v", valueType, customBaseType)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("无法将 %v 转换为 %v", valueType, customType)
|
||||
}
|
||||
Reference in New Issue
Block a user