传递切片作为参考,以反映调用者的更改[重复]

This question already has an answer here:

main declares a slice with name allOutputs (i believe its a slice of strings, not an array of strings) with zero length and 100 capacity. Then it appends a string with value "abcd" and calls myTest function which updates the array[0] with "1234" and then does an append with value "5678".

When i printed allOutputs after myTest call, i correctly see the element at the first index has an updated value of "1234". This tells me that myTest got slice as reference. But the later append of "5678" is not seen by the caller (main here) at all why its so? Remember the original slice is backed by an array with a capacity of 100. Why can't i see 5678 in main when the slice is passed by a reference?

In other words, how exactly the append works?

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
}

ACTUAL OUTPUT: [1234]

I EXPECTED: [1234, 5678]

</div>

append works exactly as you think it does!

As you can see in this playground, the append function works as you're expecting if you don't pass the allOutputs array as a parameter to myTest.

As you suspected, append may return a new array if the capacity of the original array is exceeded. In your example, the array size in myTest is not modified, however, it is a copy of allOutputs which remains unchanged.

It's best to think of an array like a string. It's a mutable block of memory. When passed as a parameter, the whole block is copied.

Your assumption that, because the array allOutputs is pre-allocated with 100 elements the call to append won't need to change array, is correct.

If you'd written this, you would have seen the results you expected.

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

One nice solution to this is:

   type myStrings []string

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

If you declare your own type, then you can define a method that can mutate the array without explicitly using the & operator.