使用golang的字符串路径变量导航到地图中

时间:2017-11-28 10:06:41

标签: dictionary go interface path navigation

我想直接导航到地图中的值。让我们更具体地使用以下代码示例,它应该直接给我“Walter”的值:(https://play.golang.org/p/tYJsvp39hn

type Signature struct{
     Name string
     Signed bool
}    

path := "Document.Signatures.1.Name"
map := map[string]interface{}{
    "Document": map[string]interface{}{
        "Signatures": []interface{}{
            Signature{ Name: "Hugo", Signed: false },
            Signature{ Name: "Walter", Signed: false },
        },
        "Otherstuff": "asadwa",
    },
    "AlsoOtherStuff": "adwaw",
}

// map.giveMe(path)
// even better (if possible:) map.change(path,"ToThisNewValue")

我已经搜索了解决方案,但我在互联网上找不到任何解决方案。也许你们其中一个人知道怎么做或者知道一个图书馆供我使用。

提前非常感谢你!

1 个答案:

答案 0 :(得分:2)

如果没有预定义的结构,将需要很多反射调用。

话虽这么说,你可以通过迭代遍历地图,每次迭代都进行类型检查并相应地处理案例。

// Splitting the path into keys
keys := strings.Split(path, ".")

var value interface{} = map1
for _, key := range keys {
    if value, err = Get(key, value); err != nil {
        break
    }
}
if err == nil {
    fmt.Println("Value:", value)
} else {
    fmt.Println("Error:", err)
}


func Get(key string, s interface{}) (v interface{}, err error) {
    var (
        i  int64
        ok bool
    )
    switch s.(type) {
    case map[string]interface{}:
        if v, ok = s.(map[string]interface{})[key]; !ok {
            err = fmt.Errorf("Key not present. [Key:%s]", key)
        }
    case []interface{}:
        if i, err = strconv.ParseInt(key, 10, 64); err == nil {
            array := s.([]interface{})
            if int(i) < len(array) {
                v = array[i]
            } else {
                err = fmt.Errorf("Index out of bounds. [Index:%d] [Array:%v]", i, array)
            }
        }
    case Signature:
        r := reflect.ValueOf(s)
        v = reflect.Indirect(r).FieldByName(key)
    }
    //fmt.Println("Value:", v, " Key:", key, "Error:", err)
    return v, err
}

Playground code