有时候需要获取一个interface{}或map[string]interface{}类型的多维map中某个key的值,只能用.(map[string]interface{})慢慢强转换以后来取,key太深的话取起来就麻烦了。因此我写了一个多维map的取值函数,类似于PHP中的多维关联数组。
函数如下:
package main
import (
"encoding/json"
"errors"
)
//MapGetValue map[string]interface{}获取值,支持多维
func MapGetValue(keys []string, data interface{}) (interface{}, error) {
var res interface{}
var err error
var copyData interface{}
var mapData map[string]interface{}
length := len(keys)
//检测keys
if length == 0 {
return res, errors.New("no key")
}
//拷贝data
copyData, err = Copy(data)
if err != nil {
return res, errors.New("map data error")
}
//data转换成map
var ok bool
if mapData, ok = copyData.(map[string]interface{}); ok == false {
return res, errors.New("map data format error")
}
//keys最后一个index
lastIndex := len(keys) - 1
//遍历查找data
for k, val := range keys {
if val2, ok2 := mapData[val]; ok2 {
//到达最后
if k == lastIndex {
res = val2
break
} else {
//转成map格式方便下一次循环
if mapData, ok2 = val2.(map[string]interface{}); ok2 == false {
err = errors.New("map key count not patch")
break
}
}
} else {
err = errors.New("not exists key " + val)
}
}
return res, err
}
//Copy 拷贝
func Copy(a interface{}) (interface{}, error) {
var d interface{}
var err error
//加码
c, err := json.Marshal(a)
if err != nil {
return d, err
}
//拷贝
err = json.Unmarshal(c, &d)
if err != nil {
return d, err
}
return d, err
}
实例如下:
map的上级和下级元素可以是map[string]interface{}类型,或者其他如map[string]int等等类型。
package main
import (
"fmt"
)
func main() {
var d interface{}
//示例一(一维)
d = map[string]string{
"a": "aaa",
}
val, _ := MapGetValue([]string{"a"}, d) //可以不用管error,如果有error,说明不存在或者格式不对
fmt.Println("示例一取值成功:", val) //输出的值为aaa
//示例二(多维)
d = map[string]interface{}{
"a": map[string]map[string]int{
"b": map[string]int{
"c": 333,
},
},
}
val, _ = MapGetValue([]string{"a", "b", "c"}, d) //可以不用管error,如果error,说明不存在或者格式不对
fmt.Println("示例二取值成功!", val) //输出的值为333
}
注意:本文归作者所有,未经作者允许,不得转载