遍历包含不同级别地图的界面地图

Iterate through a map of interface that contains different levels of maps

假设我有一个这样的界面图:

c := map[string]interface{} {
    "test":    test,
    "test2":   test2,
}

假设 testmap[string]map[string]map[string]stringtest2map[string]string

我将如何创建一个 for 循环来枚举地图的每个索引并枚举每个索引的地图?

到目前为止我得到了:

func sanitize_map(m map[string]interface{}) map[string]interface{} {
    for k, v := range m {
    //Here is where I want to enumerate through the map of k
    }
    return m
}

你可以使用反射:

import "reflect"

func sanitize_map(m map[string]interface{}) map[string]interface{} {
    for k, v := range m {
        // Do something with the key k
        kind := reflect.ValueOf(v).Kind()
        if kind == reflect.Map {
             // You have to be sure the value is of type map[string]interface{}
             newValue := v.(map[string]interface{})
             // recursively call sanitize
             sanitize_map(newValue)
        }
    }
    return m
}

注意事项是:映射中的每个值都必须是 而不是 map(原子)或 map[string]interface{}。注意 map[string]interface{}map[string]map[string]interface{} 是完全不相关的类型,您不能在第一种类型上使用第二种类型的类型断言。

但是,您可以将 map[string]map[string]string 放在 map[string]interface{} 中,如下所示:

innerMap1 := make(map[string]interface{})
// map to strings
innerMap1["a"] = "String 1"
innerMap2 := make(map[string]interface{})
// set mappings, maybe to other types

outerMap := make(map[string]interface{})
outerMap["ABC"] = innerMap1
outerMap["DEF"] = innerMap2

现在您可以将 outerMap 传递给函数,反射会自动为您 "strip" 地图层。

无需反省;使用 type assertion 并将值传回您的清理函数

func sanitizeMap(m map[string]interface{}) map[string]interface{} {
    for k, v := range m {
        _ = k
        if v, ok := v.(map[string]interface{}); ok {
            sanitizeMap(v)
        }
    }
    return m
}