1 Star 1 Fork 0

Gousing/values

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
map_any.go 9.20 KB
一键复制 编辑 原始数据 按行查看 历史
ygzhang 提交于 2025-05-13 15:20 +08:00 . 优化ToBaseX断言遍历顺序,新增测试
package values
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
"sync"
"time"
"unsafe"
)
// ToMapAny 转换目标为 map[K]any , 如果转换失败, 则返回空的map
// - 通过断言快速处理基本切片 map[TypeBase]any
// - 其他类型Map尝试反射检查后处理
// - TypeBase: string | bool | int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 | time.Time | time.Duration| time.Month | time.Weekday
func ToMapAny[K TypeBase](v any) map[K]any {
if v == nil {
return map[K]any{}
}
to, _ := ToMapAnyE[K](v)
return to
}
// ToMapAnyD 转换目标为 map[K]any , 如果转换失败, 则返回defaultVal指定的map
// - 通过断言快速处理基本切片 map[TypeBase]any
// - 其他类型Map尝试反射检查后处理
// - TypeBase: string | bool | int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 | time.Time | time.Duration| time.Month | time.Weekday
func ToMapAnyD[K TypeBase](v any, defaultVal map[K]any) map[K]any {
if v == nil {
return defaultVal
}
if to, err := ToMapAnyE[K](v); err == nil {
return to
}
return defaultVal
}
// ToMapAnyE 转换目标为 map[K]any, 如果转换失败, 则返回空的map和错误信息
// - 通过断言快速处理基本TypeBase类型切片 map[TypeBase]TypeBase
// - 其他类型Map尝试反射检查后处理
// - TypeBase: string | bool | int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 | time.Time | time.Duration| time.Month | time.Weekday
func ToMapAnyE[K TypeBase](v any) (map[K]any, error) {
return _toMapAnyE[K](UnderefVal(v))
}
// _toMapAnyE 尝试将目标转换为 map[K]any, 如果转换失败, 则返回空的map和错误信息
// - 待转换目标为已经UnderefVal处理的参数
func _toMapAnyE[K TypeBase](v any) (map[K]any, error) {
toVal := map[K]any{}
if v == nil {
return toVal, errors.New("ToMapAnyE: nil pointer not support")
}
// 先通过断言判断待转换值是否为 map[K]any / map[any]any 类型
switch vs := v.(type) {
case map[K]any:
return _toMapAnyAppend(vs)
case map[any]any:
return _toMapAnyKV[K](vs)
case []byte:
if json.Valid(vs) {
var toAny map[K]any
if err := json.Unmarshal(vs, &toAny); err == nil {
return toAny, nil
} else {
return toVal, fmt.Errorf("ToMapAnyE: []byte to map[K]any type, failed unmarshal: %s", err.Error())
}
}
return toVal, errors.New("ToMapAnyE: []byte to map[K]any type not support")
case string:
if vs != "" && strings.HasPrefix(vs, "{") && strings.HasSuffix(vs, "}") && json.Valid([]byte(vs)) {
var toAny map[K]any
if err := json.Unmarshal([]byte(vs), &toAny); err == nil {
return toAny, nil
} else {
return toVal, fmt.Errorf("ToMapAnyE: string to map[K]any type, failed unmarshal: %s", err.Error())
}
}
return toVal, errors.New("ToMapAnyE: string to map[K]any type not support")
case bool,
int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64,
complex64, complex128,
time.Time, time.Duration, time.Location, time.Month, time.Weekday, time.Ticker, time.Timer,
struct{}, chan any, func(), unsafe.Pointer,
bytes.Buffer, strings.Builder,
reflect.Type, reflect.Value, reflect.Kind,
sync.Mutex, sync.RWMutex, sync.Cond, sync.Once, sync.Pool, sync.WaitGroup, sync.Locker,
error,
json.Number:
// 如果待转换值是Golang 常用的基本类型, 则直接返回错误信息
return toVal, errors.New("ToMapAnyE: basicType to map[K]any type not support")
}
// 通过断言判断待转换值是否为 map[X]X 类型
if toVal, err, next := _toMapAnyWithKey[K, string](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, int](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, uint](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, int64](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, uint64](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, int32](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, uint32](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, int16](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, uint16](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, int8](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, uint8](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, float32](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, float64](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, float64](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, time.Time](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, time.Duration](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, time.Month](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, time.Weekday](v); !next {
return toVal, err
}
if toVal, err, next := _toMapAnyWithKey[K, bool](v); !next {
return toVal, err
}
// [4] 尝试反射检查是否为Map类型
return _toMapAnyReflect[K](v)
}
func _toMapAnyAppend[K TypeBase](vs map[K]any) (map[K]any, error) {
if vs == nil {
return map[K]any{}, errors.New("ToMapAnyE: nil pointer not support")
}
if len(vs) == 0 {
return map[K]any{}, nil
}
toVal := make(map[K]any, len(vs))
for key, val := range vs {
toVal[key] = val
}
return toVal, nil
}
func _toMapAnyKV[K TypeBase](vs map[any]any) (map[K]any, error) {
if vs == nil {
return map[K]any{}, errors.New("ToMapAnyE: nil pointer not support")
}
if len(vs) == 0 {
return map[K]any{}, nil
}
toVal := make(map[K]any, len(vs))
var toK K
for key, item := range vs {
if val, ok := key.(K); ok {
toK = val
} else if val, err := ToBaseE[K](key); err == nil {
toK = val
} else {
return map[K]any{}, fmt.Errorf("ToMapAnyE: K[%#v] to type of %T, error:%s", key, toK, err.Error())
}
toVal[toK] = item
}
return toVal, nil
}
func _toMapAnyWithKey[K TypeBase, Key TypeBase](v any) (map[K]any, error, bool) {
switch vs := v.(type) {
default:
return map[K]any{}, nil, true // Next "true" To continue
case map[Key]any:
return _toMapAnyWithLoop[K](vs)
case map[Key]string:
return _toMapAnyWithLoop[K](vs)
case map[Key]bool:
return _toMapAnyWithLoop[K](vs)
case map[Key]int:
return _toMapAnyWithLoop[K](vs)
case map[Key]int8:
return _toMapAnyWithLoop[K](vs)
case map[Key]int16:
return _toMapAnyWithLoop[K](vs)
case map[Key]int32:
return _toMapAnyWithLoop[K](vs)
case map[Key]int64:
return _toMapAnyWithLoop[K](vs)
case map[Key]uint:
return _toMapAnyWithLoop[K](vs)
case map[Key]uint8:
return _toMapAnyWithLoop[K](vs)
case map[Key]uint16:
return _toMapAnyWithLoop[K](vs)
case map[Key]uint32:
return _toMapAnyWithLoop[K](vs)
case map[Key]uint64:
return _toMapAnyWithLoop[K](vs)
case map[Key]float32:
return _toMapAnyWithLoop[K](vs)
case map[Key]float64:
return _toMapAnyWithLoop[K](vs)
case map[Key]time.Time:
return _toMapAnyWithLoop[K](vs)
case map[Key]time.Duration:
return _toMapAnyWithLoop[K](vs)
case map[Key]time.Weekday:
return _toMapAnyWithLoop[K](vs)
case map[Key]time.Month:
return _toMapAnyWithLoop[K](vs)
case map[Key]json.Number:
return _toMapAnyWithLoop[K](vs)
case map[Key]error:
return _toMapAnyWithLoop[K](vs)
}
}
func _toMapAnyWithLoop[K TypeBase, vsK TypeBase, vsV any](vs map[vsK]vsV) (map[K]any, error, bool) {
if vs == nil {
return map[K]any{}, errors.New("ToMapAnyE: nil pointer not support"), false // Next "false" To Break
}
if len(vs) == 0 {
return map[K]any{}, nil, false // Next "false" To Break
}
toVal := make(map[K]any, len(vs))
var toK K
for key, item := range vs {
if val, ok := any(key).(K); ok {
toK = val
} else if val, err := ToBaseE[K](key); err == nil {
toK = val
} else {
return map[K]any{}, fmt.Errorf("ToMapAnyE: K[%#v] to type of %T, error:%s", key, toK, err.Error()), false // Next "false" To Break
}
toVal[toK] = any(item)
}
return toVal, nil, false // Next "false" To Break
}
// [4] 尝试反射检查是否为Map类型
func _toMapAnyReflect[K TypeBase](v any) (map[K]any, error) {
// 获取输入值的反射类型和值
vType := reflect.TypeOf(v)
vValue := reflect.ValueOf(v)
if vType.Kind() == reflect.Ptr {
if vValue.IsNil() {
return map[K]any{}, errors.New("ToMapAnyE: input is a nil pointer")
}
vType = vType.Elem()
vValue = vValue.Elem()
}
// 检查是否为Map
if vType.Kind() != reflect.Map {
return map[K]any{}, fmt.Errorf("ToMapAnyE: unsupported type %T, expected map", v)
}
// 如果长度为0,直接返回空Map
if vValue.Len() == 0 {
return map[K]any{}, nil
}
toVal := make(map[K]any, vValue.Len())
// 遍历 Map 的键值对
mapKeys := vValue.MapKeys()
for _, keyRef := range mapKeys {
// 获取Map的键和值
if key, err := ToBaseE[K](keyRef.Interface()); err == nil {
toVal[key] = vValue.MapIndex(keyRef).Interface()
} else {
var toK K
return toVal, fmt.Errorf("ToMapAnyE: K[%#v] to type of %T, error:%s", key, toK, err.Error())
}
}
return toVal, nil
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/gousing/values.git
git@gitee.com:gousing/values.git
gousing
values
values
v1.0.4

搜索帮助