传递切片作为参考以反映调用方的更改

时间:2019-05-19 16:53:19

标签: arrays go append slice

main声明一个名称为allOutputs的切片(我相信它是一个字符串切片,而不是字符串数组),长度为零,容量为100。然后,它会附加一个值为“ abcd”的字符串,并调用myTest函数,该函数会将array [0]更新为“ 1234”,然后执行一个附加值为“ 5678”的事情。

allOutputs调用后打印myTest时,我正确地看到第一个索引处的元素的更新值为“ 1234”。这告诉我myTest得到了切片作为参考。但是调用者(主要在此处)根本​​看不到append中后来的"5678",为什么这样呢?还记得原始切片由容量为100的数组支持吗?为什么切片通过引用传递时主视图中看不到5678?

换句话说,追加的工作原理是什么?

import "fmt"

func myTest(array []string) {
    array[0] = "1234"
    array = append(array, "5678")
}

func main() {
    allOutputs := make([]string, 0, 100)
    allOutputs = append(allOutput, "abcd")
        fmt.Println(allOutputs) // Println1
    myTest(allOutputs)
    fmt.Println(allOutputs) // Println2
}

实际输出: [1234]

我预期: [1234,5678]

1 个答案:

答案 0 :(得分:0)

append的工作原理与您认为的完全一样!

如您在this playground中所见,如果不将append数组作为参数传递给allOutputs,则myTest函数将按预期工作。

您怀疑,如果超出了原始阵列的容量,append 可能返回一个新阵列。在您的示例中,修改了myTest中的数组大小,但是,它是allOutputs的副本,保持不变。

最好把一个数组想成一个字符串。这是可变的内存块。作为参数传递时,将复制整个块。

您的假设是正确的,因为数组allOutputs已预先分配了100个元素,因此对append的调用无需更改array

如果您写的是 this ,您会看到预期的结果。

allOutputs := make([]string, 0, 100)
allOutputs = append(allOutputs, "abcd")
fmt.Println(allOutputs) // Println1
allOutputs[0] = "1234"
allOutputs = append(allOutputs, "5678")
fmt.Println(allOutputs) // Println2

一个不错的解决方案是:

   type myStrings []string

   func (m *mystring) myTest() {
      // Do something
   }

如果您声明自己的类型,则可以定义一个方法,该方法可以在不显式使用&运算符的情况下对数组进行变异。