从Slice元素和Map元素的Struct值调用指针接收者方法的差异



我用结构体A编写了指针接收器方法,并创建了两个函数

  1. 期望A类型切片作为参数,
  2. 期望map[int]A类型映射作为参数。

都遍历a的值和调用a的pinter receiver方法,但是当它调用in map时,会出现下面提到的编译错误。切片元素值和映射值均为main.A

./main.go:28:8: cannot call pointer method on aa[k]
./main.go:28:8: cannot take the address of aa[k]

有编译错误的代码被注释,代码在下面。

package main
type A struct {
I int
}
func (a *A) Add(i int)  {
a.I += i
}
func main()  {
aa2 := []A{{I:5}}
testSlice(aa2, 10)
//aa1 := map[int]A{
//  5: {I:5},
//}
//testMap(aa1, 10)
}
func testSlice(aa []A, i int)  {
for k := range aa {
aa[k].Add(i)
}
}
//func testMap(aa map[int]A, i int)  {
//  for k := range aa {
//      aa[k].Add(i)
//  }
//}

未注释的代码在这里

请帮我澄清一下,为什么会发生这种编译错误?

在go中,map值是不可寻址的。这意味着你不能得到一个指向映射值(aa[k])的指针,因此你不能在这个值上调用一个带有指针接收器的方法。

解决方法如下:

for k := range aa {
e := aa[k]
e.Add(i)
aa[k] = e
}

首先感谢go playground,它真的很有帮助。

你的方法使用一个指针接收器,和映射,是用来存储一个键对象,如前所述,映射在go是不可寻址的(为什么不允许'不允许获取映射值的地址?),所以你需要做的是:在地图上做一个范围,1°值是关键,第二个是值所以你的结构被保存在内存中作为一个Key: struct。

一个选项是将映射声明为:

map[int]*A 

因此,当您从映射中查看值时,您可以访问指针方法。

for _,value := range aa {
value.Add(i)
}

操场在这里:https://play.golang.org/p/eVA8ujrdcO4

另一种解决方案是将map[i]A保留为map[i]A,只是在for范围内:将值返回给它的键,如下所示:

for k,value := range aa {
value.Add(i)
aa[k]=value
} 

操场在这里:https://play.golang.org/p/k-Qr8oYpL6j

最新更新