有人可以向我解释为什么r.a的输出为空,因为我在列表中添加了2值?
package main
import (
"fmt"
)
func main() {
var r R
r.b = make(map[int]int)
r.add()
fmt.Println(r) // outputs {[] map[2:2]}
}
type R struct {
a []int
b map[int]int
}
func (r R) add() {
r.a = append(r.a, 2)
r.b[2] = 2
}
答案 0 :(得分:1)
“围棋之旅”的简短摘录指出:
带有指针接收器的方法可以将值修改为 接收点[...]。由于方法通常需要修改其 接收器,指针接收器比值接收器更常见。
为什么r.b
根本没有被修改而r.a
正确显示?
正如我在下面的回答中所述,您的add()
方法是一个值接收者。因此,它将采用您初始化的结构(即r
),将其复制然后进行相应的修改。因为您已经在r.b
函数中的main()
下初始化了一个新映射,所以这里仅复制对此映射的引用,而不复制整个映射。因此,对地图的操作有效,但对切片r.a
无效。但是,为什么r.a
根本没有变化?这是因为位于append()
方法中的add()
在您的a
属性下存储了一个新的slice头,并指向基础数组的不同部分。最后,您的值接收器方法add()
复制了r
,在属性a
下设置了一个新的slice头,并且从未更改原始结构r
,是在main()
函数中定义的,因为它是通过值接收器方法add()
复制的。
在您的情况下,add()
方法是所谓的值接收器方法,它无法直接对位于r
函数中的已定义结构main()
进行任何操作,但可以对其进行复制并执行之后的操作。因此,您需要将add()
方法转换为指针接收器方法,如下所示:
func (r *R) add() {
r.a = append(r.a, 2)
r.b[2] = 2
}
现在,该方法将获取在r
函数中初始化的结构main()
的实际引用,并对其进行相应的修改。
如何在不将您的add()
方法更改为指针接收器的情况下工作?
您只需要在add()
方法中返回复制的结构,如下所示:
package main
import (
"fmt"
)
func main() {
var r R
r.b = make(map[int]int)
fmt.Println(r.add()) // outputs {[2] map[2:2]}
}
type R struct {
a []int
b map[int]int
}
func (r R) add() R {
r.a = append(r.a, 2)
r.b[2] = 2
return r
}