我有这个代码,我在一个函数中追加一个struct数组。该更改不会出现在其他功能中。
type my struct{
arr []int
}
func New_my() *my {
m := new (my)
return m
}
func (m my) Dosomething(){
m.arr = append(m.arr,1)
m.arr = append(m.arr,2)
m.arr = append(m.arr,3)
}
func (m my) Dosomethingelse(){
fmt.Println(m.arr)
}
func main(){
m:= New_my()
m.Dosomething()
m.Dosomethingelse()
}
输出结果为:
[]
请解释一下发生了什么?为什么更改没有出现在数组中?
答案 0 :(得分:2)
如果您是新手,请完全执行tour of go和effective go文档。 Go是一种新语言,并且具有奇怪的想法组合,因此官方文档是最佳起点。
首先,您使用的是切片而不是数组。 (阅读this以了解切片)
代码中的错误是因为Dosomething()是为my
而不是*my
定义的。这解释为here。
只需将其更改为:
func (m *my) Dosomething(){
m.arr = append(m.arr,1)
m.arr = append(m.arr,2)
m.arr = append(m.arr,3)
}
在go中,所有内容都按值传递,因此在您的代码中,您将结构的副本传递给函数Dosomething()
,并且因为切片的容量为0,append
函数会创建一个新的底层数组并返回对它的引用,当你执行:
m.arr = append(...)
新切片(使用新数组)丢失,因为它存储在m中,它是原始结构的副本,如果m是*my
,则新切片将替换arr属性中的前一个切片。
答案 1 :(得分:0)
在Go中,所有内容都按值传递,包括提供给接收者的这个/ self / me / m
参数(也称为方法)。
在Go中,如果某些内容似乎没有按值传递,则传递指向它的指针或包含指针的结构(如字符串,切片等的情况)正在传递。
这意味着您现在DoSomething
获取自我对象的副本并附加到该对象上。
因此,在这种情况下,Topo是正确的,您只需要更改DoSomething()
以将其self / this / m
参数作为指针传递。
func (m *my) Dosomething(){
m.arr = append(m.arr,1)
m.arr = append(m.arr,2)
m.arr = append(m.arr,3)
}
我认为这是玩具代码,但有几个注意事项:
你可以更有效地写这个:
func (m *my) Dosomething(){
m.arr = append(m.arr,[]int{1,2,3}...)
}
将New_my()
重命名为newMy()