package maputils import ( "errors" "strconv" "strings" ) const ( pathSeparator = "." ) // GetValueByPath 通过路径查询map的值,常用查找unmarshal到map的json或者yaml中的值 // 参数: // m: key是string类型的map,值可以是任意类型,如果map下的值还是map,则map的key必须为string类型 // path: 路径,如foo1.foo1_sub.[0],key为foo1的值是一个map[string]any,foo1_sub对应的值是一个slice,如果需要取slice的某一个值,可以用[n]获取 // 返回值: // 对应的值和错误 func GetValueByPath(m map[string]any, path string) (any, error) { if m == nil || strings.TrimSpace(path) == "" { return nil, errors.New("没有传递需要查找的数据或路径") } var retValue any var currentFind any currentFind = m pathParts := strings.Split(path, pathSeparator) for _, pathPart := range pathParts { if strings.HasPrefix(pathPart, "[") && strings.HasSuffix(pathPart, "]") { indexStr := strings.TrimLeft(strings.TrimRight(pathPart, "]"), "[") index, err := strconv.Atoi(strings.Trim(indexStr, " ")) if err != nil { return nil, err } findSlice, ok := currentFind.([]any) if ok { if index > len(findSlice)-1 { retValue = nil } else { retValue = findSlice[index] } } else { findMapSlice, ok := currentFind.([]map[string]any) if !ok { return nil, errors.New("对应slice路径的值不是slice: " + pathPart) } if index > len(findMapSlice)-1 { retValue = nil } else { retValue = findMapSlice[index] } } } else { findMap, ok := currentFind.(map[string]any) if !ok { return nil, errors.New("对应map路径的值不是map[string]any: " + pathPart) } value, ok := findMap[pathPart] if !ok { return nil, nil } retValue = value } if retValue == nil { return nil, nil } currentFind = retValue } return retValue, nil } // GetValueByKey 通过key查询map的值 // 模板参数: // K是map的key的类型,V是map值的类型 // 参数: // m: 从这个map获取值 // key: map的key // 返回值: // 对应的值和获取是否成功,失败可能有两个原因:对应的key不存在或者V类型转换失败 func GetValueByKey[K comparable, V any](m map[K]any, key K) (V, bool) { var zeroValue V mapValue, ok := m[key] if !ok { return zeroValue, false } v, ok := mapValue.(V) if !ok { return zeroValue, false } return v, true } // SortMap 可以排序的map // 模板参数: // K是map的key的类型,V是map值的类型 type SortMap[K comparable, V any] struct { sortedKeys []K m map[K]V } // Range 遍历排序后的map // 模板参数: // K是map的key的类型,V是map值的类型 // 参数: // callback: 遍历回调 func (sortMap *SortMap[K, V]) Range(callback func(index int, key K, value V)) { if callback != nil { for i, key := range sortMap.sortedKeys { callback(i, key, sortMap.m[key]) } } } // Sort 排序map // 模板参数: // K是map的key的类型,V是map值的类型 // 参数: // m: 需要排序的map // sortKeysFunc: 对key进行排序的回调函数 // 返回值: // SortMap指针,之后可以调用Range遍历排序后的map func Sort[K comparable, V any](m map[K]V, sortKeysFunc func(keys []K)) *SortMap[K, V] { keys := make([]K, 0) for key := range m { keys = append(keys, key) } if sortKeysFunc != nil { sortKeysFunc(keys) } return &SortMap[K, V]{ sortedKeys: keys, m: m, } }