0
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?

Community
  • 1
  • 1
Sotter.liu
  • 115
  • 4
  • 10
  • https://tour.golang.org/moretypes/7 ff and https://blog.golang.org/slices. Basically you modify slice1 which is no longer backed by the same array than slice after appending to it. – Volker Sep 07 '17 at 07:42
  • Just a tip... setting the capacity as well size is redundant if they are the same. `make([]int, 10, 10)` might as well be `make([]int, 10)` – Ari Seyhun Sep 07 '17 at 07:48
  • 1
    With ref. to the answers below, try this program https://play.golang.org/p/WM12iW9A4z, which sets the length 5 and capacity 10, you'll hopefully realize what's happening. – Ravi R Sep 07 '17 at 09:09
  • Basically, an append operation will require allocation of a newer array for a slice when the existing allocation is filled up (length = capacity) – Ravi R Sep 07 '17 at 09:15

2 Answers2

8

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.

icza
  • 389,944
  • 63
  • 907
  • 827
2

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

Zan Lynx
  • 53,022
  • 10
  • 79
  • 131