I read this article that made some quizzes, and I failed to guess the output of some of them…
The first one (playground):
package main
import "fmt"
func surprise(a []int) {
for i := range(a) {
a[i] = 5
}
fmt.Println(a)
}
// Quiz #1
func main() {
a := []int{1, 2, 3, 4}
surprise(a)
fmt.Println(a)
}
output
[5 5 5 5]
[5 5 5 5]
wile the second (playground):
package main
import "fmt"
func surprise(a []int) {
a = append(a, 5)
for i := range(a) {
a[i] = 5
}
fmt.Println(a)
}
// Quiz #2
func main() {
a := []int{1, 2, 3, 4}
surprise(a)
fmt.Println(a)
}
output:
[5 5 5 5 5]
[1 2 3 4]
so I think that this is because in the second quiz a is copied to local function.
but then I was surprised with the fourth quiz(playground) :
package main
import "fmt"
func surprise(a []int) {
a = append(a, 5)
for i := range(a) {
a[i] = 5
}
fmt.Println(a)
}
// Quiz #4
func main() {
a := []int{1, 2, 3, 4}
a = append(a, 5)
surprise(a)
fmt.Println(a)
}
opuput:
[5 5 5 5 5 5]
[5 5 5 5 5]
So why is that?
>Solution :
A slice is a view over an array. When you append new values to a slice that does not have enough capacity, a new array is allocated with larger capacity and the contents of the old array are copied to the new array.
So in the second case, the slice is appended in the function, so at that point a new array is allocated, and the function sets all the values of the new array to 5. The slice in main remains unchanged.
In the third case the slice is appended in main, which creates a new array twice the size of the original. When the function appends a new value to that array, there is no need to resize it, so both main and the function work on the same underlying array, with the difference that the slice in the function is one larger than the one in main. They both share the same underlying array though.