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.