【原创】golang map多维key获取值

小豆丁 1年前 ⋅ 204 阅读

有时候需要获取一个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
}

全部评论: 0

    我有话说: