英文:
Append to an array from another function?
问题
在这段代码中,你定义了一个名为my
的结构体,其中包含一个整型切片arr
。然后你定义了一个New_my
函数,用于创建并返回一个指向my
结构体的指针。
接下来,你定义了两个方法Dosomething
和Dosomethingelse
,它们都接收一个my
结构体的值作为接收者。在Dosomething
方法中,你使用append
函数向arr
切片中追加了三个整数。而在Dosomethingelse
方法中,你打印了arr
切片的内容。
在main
函数中,你首先通过调用New_my
函数创建了一个my
结构体的实例,并将其赋值给变量m
。然后你调用了m
的Dosomething
方法和Dosomethingelse
方法。
然而,输出结果却是一个空的切片[]
。
这是因为在Dosomething
和Dosomethingelse
方法中,你使用的是my
结构体的值接收者,而不是指针接收者。在Go语言中,值接收者会对接收到的结构体进行复制,而指针接收者则会直接操作原始结构体。
因此,在Dosomething
方法中,对m.arr
的修改只会影响到Dosomething
方法内部的副本,而不会影响到main
函数中的m
实例。所以,当你调用Dosomethingelse
方法时,m.arr
仍然是空的。
要解决这个问题,你可以将Dosomething
和Dosomethingelse
方法的接收者改为指针类型,即将方法签名中的my
改为*my
。这样,在方法中对m.arr
的修改就会直接影响到main
函数中的m
实例。
修改后的代码如下:
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()
}
这样修改后,输出结果将会是[1 2 3]
,即Dosomething
方法中对m.arr
的修改会在Dosomethingelse
方法中得到反映。
英文:
I have this code in which I am appending to an array of a struct in one function. The change does not appear in the other function.
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()
}
The output is:
[]
Please, explain what is happening? Why does the change not appear in the array?
答案1
得分: 2
如果你对Go语言还不熟悉,你应该完全参加一下Go之旅和Effective Go文档。Go是一种新的语言,结合了一些奇特的思想,所以官方文档是最好的起点。
首先,你正在使用切片而不是数组。(阅读这个来理解切片)
你代码中的错误是因为Dosomething()
是为my
而不是*my
定义的。这在这里有解释。
只需将其更改为:
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是原始结构体的副本,如果m是*my
,新的切片将替换arr属性中的先前切片。
英文:
If you are new to go you should totally do the tour of go and the effective go document. Go is a new language and with a strange combination of ideas so the official documentation is the best place to start.
First of all you are using a slice not an array. (Read this to understand slices)
The error in your code is because Dosomething() is defined for my
instead of *my
. This is explained here.
Just change it to:
func (m *my) Dosomething(){
m.arr = append(m.arr,1)
m.arr = append(m.arr,2)
m.arr = append(m.arr,3)
}
In go everything is passed by value so in your code you are passing a copy of the struct to the function Dosomething()
, and because the capacity of the slice is 0, the append
function creates a new underlying array and returns a reference to it, and when yo do:
m.arr = append(...)
the new slice (using the new array) is lost because it is stored in m that is a copy of the original struct, if m were a *my
the new slice would replace the previous in the arr property.
答案2
得分: 0
在Go语言中,所有东西都是按值传递的,包括提供给接收器(也称为方法)的this/self/me/m参数。
在Go语言中,如果某个东西看起来不是按值传递的,那么要么传递的是指向它的指针,要么传递的是包含指针的结构体(例如string、slice等)。
这意味着现在你的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()
。
英文:
In Go everything is passed by value, including the this/self/me/m
argument provided to receivers (aka methods).
In Go if something does not appear to be passed by value, then either a pointer to it, or a struct containing a pointer (as is the case for string, slice, etc) is being passed.
That means right now your DoSomething
gets a copy of the self-object and appends to that.
So in this case Topo is correct, you just need to change DoSomething()
to pass its self/this/m
argument as a pointer.
func (m *my) Dosomething(){
m.arr = append(m.arr,1)
m.arr = append(m.arr,2)
m.arr = append(m.arr,3)
}
I assume this is toy code, but a couple of notes:
You could write this more efficiently as:
func (m *my) Dosomething(){
m.arr = append(m.arr,[]int{1,2,3}...)
}
And it would be more idiomatic to rename New_my()
to newMy()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论