诚如成诚的评论所述:
另请参阅http://golang.org/doc/effective_go.html#maps。重要的部分实际上是“对基础数据结构的引用”。这也适用于切片。
但是,这里的任何解决方案似乎都无法为适当的深层复制(也包括切片)提供解决方案。
我略微更改了Francesco Casula的答案,以适合地图和切片。
这应该包括复制地图本身以及复制任何子地图或切片。两者都受到相同的“基础数据结构”问题的影响。它还包括一个实用程序功能,可直接在片上执行相同类型的Deep Copy。
请记住,结果映射中的切片将为类型[]interface{}
,因此在使用它们时,您将需要使用类型断言来检索所需类型中的值。
用法示例
copy := CopyableMap(originalMap).DeepCopy()
源文件(util.go
)
package utils
type CopyableMap map[string]interface{}
type CopyableSlice []interface{}
func (m CopyableMap) DeepCopy() map[string]interface{} {
result := map[string]interface{}{}
for k,v := range m {
mapvalue,isMap := v.(map[string]interface{})
if isMap {
result[k] = CopyableMap(mapvalue).DeepCopy()
continue
}
slicevalue,isSlice := v.([]interface{})
if isSlice {
result[k] = CopyableSlice(slicevalue).DeepCopy()
continue
}
result[k] = v
}
return result
}
func (s CopyableSlice) DeepCopy() []interface{} {
result := []interface{}{}
for _,v := range s {
mapvalue,isMap := v.(map[string]interface{})
if isMap {
result = append(result, CopyableMap(mapvalue).DeepCopy())
continue
}
slicevalue,isSlice := v.([]interface{})
if isSlice {
result = append(result, CopyableSlice(slicevalue).DeepCopy())
continue
}
result = append(result, v)
}
return result
}
测试文件(util_tests.go
)
package utils
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestCopyMap(t *testing.T) {
m1 := map[string]interface{}{
"a": "bbb",
"b": map[string]interface{}{
"c": 123,
},
"c": []interface{} {
"d", "e", map[string]interface{} {
"f": "g",
},
},
}
m2 := CopyableMap(m1).DeepCopy()
m1["a"] = "zzz"
delete(m1, "b")
m1["c"].([]interface{})[1] = "x"
m1["c"].([]interface{})[2].(map[string]interface{})["f"] = "h"
require.Equal(t, map[string]interface{}{
"a": "zzz",
"c": []interface{} {
"d", "x", map[string]interface{} {
"f": "h",
},
},
}, m1)
require.Equal(t, map[string]interface{}{
"a": "bbb",
"b": map[string]interface{}{
"c": 123,
},
"c": []interface{} {
"d", "e", map[string]interface{} {
"f": "g",
},
},
}, m2)
}