结构的映射与Go中的结构数组

Gre*_*ine 6 struct map go slice

假设我有一个带字符串属性b的简单结构a:

type A struct {
    B string
}
Run Code Online (Sandbox Code Playgroud)

以下代码使用A类型的数组:

testArray := []A{A{}}
testArray[0].B = "test1"
fmt.Println(testArray[0].B)
Run Code Online (Sandbox Code Playgroud)

将按预期打印出"test1".

但是这段代码似乎同样简单:

testMap := make(map[string]A)
testMap["key"] = A{}
testMap["key"].B = "test2"
fmt.Println(testMap["key"].B)
Run Code Online (Sandbox Code Playgroud)

不会打印出"test2",而是会导致以下错误:

无法分配到testMap ["key"].B

那么,为什么分配给映射中的子属性会导致错误,同时分配给数组中的子属性按预期工作?我想知道为什么这对地图不起作用以及为什么它对数组起作用.我也很想知道他们为什么设计这两种数据结构之间存在差异的语言.

ian*_*ant 11

我在邮件列表上回答了一些问题,但简短的解释是这不起作用,因为地图条目不可寻址.这意味着您无法获取地图中条目的地址.这是因为向地图添加新值可能会导致地图条目四处移动,从而地址会发生变化.由于您无法获取地图中条目的地址,因此所有地图操作都使用整个值:从地图复制整个值,将整体添加到地图中.分配给映射中的结构的一个字段将需要读取 - 修改 - 写入操作,映射不支持(它们可以,但它们不支持,并且支持它们需要成本).

数组和切片中的元素是可寻址的,因为它们在创建后不会移动.


jos*_*hlf 5

问题是在 map 示例中,testMap["key"]返回的是文字,而不是指针。这意味着修改它是没有意义的,所以编译器不允许它。它基本上相当于:

v := testMap["key"]
v.B = "test2"
Run Code Online (Sandbox Code Playgroud)

...然后再也不使用v了。它没有效果。这相当于从不首先执行这两行。这就是编译器不允许你这样做的原因。另一方面,如果你把它做成一个指向A的指针的映射,你就会做生意。这编译:

testMap := make(map[string]*A)
testMap["key"] = &A{}
testMap["key"].B = "test2"
Run Code Online (Sandbox Code Playgroud)

这样做的原因是取消引用和分配给一个指针值确实有效果。