Go 如何复制地图?

Go 如何复制地图?,go,Go,我试图将一个映射(amap)的内容复制到另一个映射(aSuperMap)中,然后清除amap,以便它可以在下一次迭代/循环中获取新值。 问题是你不能在超级地图中清除地图。 下面是一些伪代码 for something := range fruits{ aMap := make(map[string]aStruct) aSuperMap := make(map[string]map[string]aStruct) for x := range so

我试图将一个映射(
amap
)的内容复制到另一个映射(
aSuperMap
)中,然后清除
amap
,以便它可以在下一次迭代/循环中获取新值。 问题是你不能在超级地图中清除地图。 下面是一些伪代码

for something := range fruits{
        aMap := make(map[string]aStruct)
        aSuperMap := make(map[string]map[string]aStruct)

        for x := range something{
            aMap[x] = aData
            aSuperMap[y] = aMap
            delete(aMap, x)
    }
//save aSuperMap
  saveASuperMap(something)

}
我也尝试过一些动态的东西,但显然它会抛出一个错误(不能赋值为nil)


问题是如何创建关联贴图?在PHP中,我只使用aSuperMap[y][x]=aData。看来葛朗没有什么明显的办法。如果我删除
delete(aMap,x)
它在超级映射中的引用也会被删除。如果我不删除它,超级地图将以重复数据结束。基本上,在每个循环中,它都会得到新值加上所有旧值的
aMap

您不是在复制地图,而是在复制对地图的引用。因此,您的
delete
会修改原始贴图和超级贴图中的值。要复制地图,必须使用
for
循环,如下所示:

for k,v := range originalMap {
  newMap[k] = v
}
下面是一个来自现已退役的SO文档的示例:

// Create the original map
originalMap := make(map[string]int)
originalMap["one"] = 1
originalMap["two"] = 2

// Create the target map
targetMap := make(map[string]int)

// Copy from the original map to the target map
for key, value := range originalMap {
  targetMap[key] = value
}
摘自。原作者是。有关归属的详细信息,请访问。该来源已根据获得许可,可在中找到。参考主题ID:732和示例ID:9834


单个元素复制,它似乎只适用于一个简单的示例

maps := map[string]int {
    "alice":12,
    "jimmy":15,
}

maps2 := make(map[string]int)
for k2,v2 := range maps {
    maps2[k2] = v2
}

maps2["miki"]=rand.Intn(100)

fmt.Println("maps: ",maps," vs. ","maps2: ",maps2)

我会使用递归以防万一,这样您就可以深入复制
map
,并避免在更改
map
元素时发生意外

下面是一个例子,在autils.go

包utils
func CopyMap(m map[string]接口{})map[string]接口{}{
cp:=make(映射[字符串]接口{})
对于k,v:=范围m{
vm,ok:=v.(映射[string]接口{})
如果可以的话{
cp[k]=CopyMap(vm)
}否则{
cp[k]=v
}
}
返回cp
}
及其测试文件(即utils_test.go):

包utils
进口(
“测试”
“github.com/stretchr/authentic/require”
)
func TestCopyMap(t*testing.t){
m1:=map[string]接口{}{
“a”:“bbb”,
“b”:映射[字符串]接口{}{
“c”:123,
},
}
m2:=CopyMap(m1)
m1[“a”]=“zzz”
删除(m1,“b”)
require.Equal(t,map[string]接口{}{“a”:“zzz},m1)
require.Equal(t,map[string]接口{}{
“a”:“bbb”,
“b”:映射[字符串]接口{}{
“c”:123,
},
},平方米)
}

如果您需要
映射
键而不是
字符串
,则应该很容易进行调整。您必须手动将每个键/值对复制到新的
映射
。这是一个循环,人们在任何时候需要深度拷贝
地图时都必须重新编程

通过使用从包中安装
mapper
,可以自动生成此函数

go-get-u github.com/drgrib/maps/cmd/mapper
跑步

mapper-types字符串:aStruct
这将生成文件
map\u float\u astruct.go
,其中不仅包含地图的(深)副本
副本,还包含其他“缺失的”
map
函数
ContainsKey
ContainsValue
GetKeys
,以及
GetValues

func ContainsKeyStringAStruct(m map[string]aStruct,k string)bool{
_,ok:=m[k]
返回ok
}
func包含value stringastruct(m map[string]aStruct,v aStruct)bool{
对于u,m值:=范围m{
如果mValue==v{
返回真值
}
}
返回错误
}
func getkeystringastruct(m map[string]aStruct)[]字符串{
键:=[]字符串{}
对于k,u:=范围m{
keys=追加(keys,k)
}
返回键
}
func GetValuesStringAStruct(m map[string]aStruct)[]aStruct{
值:=[]aStruct{}
对于u,v:=范围m{
值=附加(值,v)
}
返回值
}
func CopyStringAStruct(m map[string]aStruct)map[string]aStruct{
copyMap:=map[string]aStruct{}
对于k,v:=范围m{
copyMap[k]=v
}
返回copyMap
}
完全披露:我是这个工具的创造者。我创建了它和它的包含包,因为我发现自己不断地为不同类型组合的Go
map
重写这些算法。

如中所述:

另见。重要的部分实际上是“对底层数据结构的引用”。这也适用于切片

然而,这里的任何解决方案似乎都不能提供一个包含切片的正确深度拷贝解决方案。

我稍微做了一些修改,以适应贴图和切片


这应该包括复制贴图本身,以及复制任何子贴图或切片。两者都受到相同的“基础数据结构”问题的影响。它还包括一个实用程序函数,用于直接在切片上执行相同类型的深度复制

请记住,结果映射中的切片将是
[]接口{}
类型,因此在使用它们时,您需要使用来检索预期类型中的值

示例用法

copy:=CopyableMap(originalMap).DeepCopy()
源文件(
util.go

包utils
键入CopyableMap映射[字符串]接口{}
类型CopyableSlice[]接口{}
//DeepCopy将创建此地图的深度副本。这件事的深度
//复印件包罗万象。当需要时,将同时考虑贴图和切片
//制作副本。
func(m CopyableMap)DeepCopy()映射[字符串]接口{}{
结果:=map[string]接口{}{}
对于k,v:=范围m{
//处理地图
mapvalue,isMap:=v.(map[string]接口{})
如果isMap{
结果[k]=CopyableMap(mapvalue).DeepCopy()
持续
}
//柄片
maps := map[string]int {
    "alice":12,
    "jimmy":15,
}

maps2 := make(map[string]int)
for k2,v2 := range maps {
    maps2[k2] = v2
}

maps2["miki"]=rand.Intn(100)

fmt.Println("maps: ",maps," vs. ","maps2: ",maps2)
package main

import (
   "bytes"
   "encoding/gob"
)

func copyMap(in, out interface{}) {
   buf := new(bytes.Buffer)
   gob.NewEncoder(buf).Encode(in)
   gob.NewDecoder(buf).Decode(out)
}

func main() {
   a := map[string]int{"month": 12, "day": 31}
   b := make(map[string]int)
   copyMap(a, &b)
}
package main

import (
   "fmt"
   "net/url"
)

func copyVal(v url.Values) url.Values {
   u := url.URL{
      RawQuery: v.Encode(),
   }
   return u.Query()
}

func main() {
   a := url.Values{
      "west": {"left"}, "east": {"right"},
   }
   b := copyVal(a)
   fmt.Println(b)
}