185 lines
4.7 KiB
Go
185 lines
4.7 KiB
Go
|
|
package structx
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"encoding/json"
|
|||
|
|
"fmt"
|
|||
|
|
"reflect"
|
|||
|
|
"strconv"
|
|||
|
|
|
|||
|
|
"code.yun.ink/pkg/convx"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// converterFunc 类型转换函数
|
|||
|
|
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,
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// 转换为字符串
|
|||
|
|
func convertToString(item interface{}) string {
|
|||
|
|
if str, ok := item.(string); ok {
|
|||
|
|
return str
|
|||
|
|
}
|
|||
|
|
return fmt.Sprintf("%v", item)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 转换为数字(float64)
|
|||
|
|
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 convertToTypeAlias(aliasType reflect.Type, value interface{}) (interface{}, error) {
|
|||
|
|
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("无法转换类型")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 类型转换函数
|
|||
|
|
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转换未实现")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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
|
|||
|
|
}
|
|||
|
|
}
|