从另一个函数向数组追加元素?

huangapple go评论75阅读模式
英文:

Append to an array from another function?

问题

在这段代码中,你定义了一个名为my的结构体,其中包含一个整型切片arr。然后你定义了一个New_my函数,用于创建并返回一个指向my结构体的指针。

接下来,你定义了两个方法DosomethingDosomethingelse,它们都接收一个my结构体的值作为接收者。在Dosomething方法中,你使用append函数向arr切片中追加了三个整数。而在Dosomethingelse方法中,你打印了arr切片的内容。

main函数中,你首先通过调用New_my函数创建了一个my结构体的实例,并将其赋值给变量m。然后你调用了mDosomething方法和Dosomethingelse方法。

然而,输出结果却是一个空的切片[]

这是因为在DosomethingDosomethingelse方法中,你使用的是my结构体的值接收者,而不是指针接收者。在Go语言中,值接收者会对接收到的结构体进行复制,而指针接收者则会直接操作原始结构体。

因此,在Dosomething方法中,对m.arr的修改只会影响到Dosomething方法内部的副本,而不会影响到main函数中的m实例。所以,当你调用Dosomethingelse方法时,m.arr仍然是空的。

要解决这个问题,你可以将DosomethingDosomethingelse方法的接收者改为指针类型,即将方法签名中的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()

huangapple
  • 本文由 发表于 2014年11月19日 00:10:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/26998770.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定