从另一个函数追加到数组?

时间:2014-11-18 16:10:22

标签: arrays go

我有这个代码,我在一个函数中追加一个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()
}

输出结果为:

[]

请解释一下发生了什么?为什么更改没有出现在数组中?

2 个答案:

答案 0 :(得分:2)

如果您是新手,请完全执行tour of goeffective 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()

会更加惯用