Ramses Aldama
Ramses Aldama

Reputation: 335

Golang slice append built-in function returning value

The return value of slice2 of this code is [[1 1][1 1]].
And that got me confuse because I was expecting [[0 0][1 1]].
I can't figure it out why is returning [[1 1][1 1]] and not [[0 0][1 1]].
I would appreciate if someone can explain that. Thanks.

slice := []int{0, 0}
slice2 := [][]int{}

for i := range slice {
    slice[0] = i
    slice[1] = i
    slice2 = append(slice2, slice)
}
fmt.Println(slice2)

You can check the code in this link play.golang.org

Upvotes: 1

Views: 2353

Answers (3)

jmaloney
jmaloney

Reputation: 12320

A slice is a descriptor of an array segment. It consists of a pointer to the array, the length of the segment, and its capacity (the maximum length of the segment).

In your case your are appending a slice(pointer) not the slice's values. To get the desired result you have to declare a new slice in each iteration and append the new slice to slice2.

func main() {
    slice := []int{0, 0}
    slice2 := [][]int{}

    for i := range slice {
        ns := []int{0, 0}
        ns[0] = i
        ns[1] = i
        slice2 = append(slice2, ns)
    }
    fmt.Println(slice2) // Outputs: [[0 0] [1 1]]
}

Playground

Upvotes: 1

Derlin
Derlin

Reputation: 9881

The problem is that what you append to slice2 is a reference to slice, not the values contained in slice at the time of the call.

This means that at the end, slice2 contains two pointers to the same slice. Any changes to the slice variable will be reflected to slice2 and vice-versa: they point to the same location in memory.

As a proof, just do:

slice2[0][1] = 2
fmt.Println(slice2)
fmt.Println(slice)

You will get:

[[1 2] [1 2]]
[1 2] 

Upvotes: 0

RayfenWindspear
RayfenWindspear

Reputation: 6284

When you range over the slice, it is not giving you the VALUES of the slice, it is giving you the indexes. This for loop is equivalent to for i:=0; i < len(slice); i++ {}. So by the time it gets through iteration, both values are in slice are 1, and you have appended it to slice2 twice.

If you wanted the values of the slice, you would need to do for i, v := range slice {} which would give you both the indexes and the values. You could use _ in place of i if you didn't want the index.

Also note that appending slice twice like this appends the same exact slice because slices are allocated as pointers on the heap and it is therefore a pointer to the slice. Thus slice2[0] == slice2[1] because it is the same exact slice.

Upvotes: 1

Related Questions