【发布时间】:2021-02-01 18:29:49
【问题描述】:
我的应用需要采用大量嵌套的 map[string]interface{} 实例并将它们转换为平面地图。
例如:
{
"foo": {
"jim":"bean"
},
"fee": "bar",
"n1": {
"alist": [
"a",
"b",
"c",
{
"d": "other",
"e": "another"
}
]
},
"number": 1.4567,
"bool": true
}
之后:
json.Unmarshal([]byte(input), &out)
result = Flatten(m.(map[string]interface{}))
变成:
{
"foo.jim": "bean",
"fee": "bar",
"n1.alist.0": "a",
"n1.alist.1": "b",
"n1.alist.2": "c",
"n1.alist.3.d": "other",
"n1.alist.3.e": "another",
"number": 1.4567,
"bool": true,
}
目前我正在使用以下代码:
func Flatten(m map[string]interface{}) map[string]interface{} {
o := map[string]interface{}{}
for k, v := range m {
switch child := v.(type) {
case map[string]interface{}:
nm := Flatten(child)
for nk, nv := range nm {
o[k+"."+nk] = nv
}
case []interface{}:
for i := 0; i < len(child); i++ {
o[k+"."+strconv.Itoa(i)] = child[i]
}
default:
o[k] = v
}
}
return o
}
此代码的内存效率非常低,当展平 ~800 个地图时,使用了 ~8 GiB 内存。 我尝试过传递指针而不是副本,但这不会改变内存使用情况。我是否必须进行某种类型的手动内存管理? Go 应该垃圾收集任何未使用的内存,但可能是我没有以某种方式释放它。
【问题讨论】:
-
您是否尝试过只使用一个结果映射并将其传递给
Flatten的每次调用以及指向该点的路径(即连接键)?这样您就不必在每次调用时创建新映射并在Flatten返回后复制条目。
标签: go memory-leaks garbage-collection pass-by-reference flatten