Sotter.liu
Sotter.liu

Reputation: 125

Confused about append() behavior on slices

func main() {
    slice := make([]int, 10, 10)
    slice[0] = 0
    slice[1] = 1

    slice1 := slice
    slice1[0] = 10000
    fmt.Println(slice)

    slice1 = append(slice1, 100)
    slice1[0] = 20000

    fmt.Println(slice)
}

result:

[10000 1 0 0 0 0 0 0 0 0]

[10000 1 0 0 0 0 0 0 0 0]

In my understanding, slice is a pointer, slice1 and slice point to the same array, and the first output also proves this. But why did slice's value remain unchanged after the append operation changed slice1?

Upvotes: 0

Views: 225

Answers (2)

icza
icza

Reputation: 417512

The append() didn't change slice1; it can't as everything in Go is passed by value, so it only receives a copy of it. Since initially you created the slice with capacity equal to its length (make([]int, 10, 10)), any append operation with more than 0 elements requires allocation of a new, bigger array. This is what your append() call does. And it copies over the contents of the old array, and returns a slice value (slice header) pointing to the new array. And you assign the return value to slice1, and this assignment is what changes slice1.

Any assignment to slice1 does not change the value of slice, they are 2 distinct variables, 2 distinct slice headers. So the appended elements will not be visible in slice. And since the append() had to create a new array, changes made to the elements of slice1 and slice will also not be reflected in one another anymore.

To see what's inside a slice header, see Are golang slices pass by value?

To learn more about slices, read blog post Go Slices: usage and internals.

Upvotes: 8

Zan Lynx
Zan Lynx

Reputation: 54325

Because an append can decide to return an entirely new copy of the underlying array.

Upvotes: 2

Related Questions