1

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

3 Answers 3

1

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

Sign up to request clarification or add additional context in comments.

Comments

1

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.

1 Comment

Specifically, a slice is a structure with 3 fields: a pointer to an underlying array, a capacity, and a length. Since you're updating the items of the slice by index, you're altering the underlying array. Since you're appending the same slice twice, both refer to the same underlying array, so altering the values in the second loop iteration alters what the first slice has as values as well.
0

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] 

1 Comment

Thanks for your explanation. Now everything make sense.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.