Golang切片参考混乱

package main

import (
    "fmt"
)

func main() {
    values := make([]int, 0, 100)
    val := make([][]int, 2)
    for i:=0; i<2; i++ {
        values = values[:0]
        for j:=0; j<2; j++ {
            values = append(values, i+j)
        }
        val[i] = values
        fmt.Println(values, val) //
    }
    fmt.Println(val)
}

https://play.golang.org/p/5x60VfDXbFw

when appending slice,val is expected to be [[0, 1], [1, 2]], but got [[1,2], [1,2]]

This happens because the slice val contains pointers to its subslices, rather than the subslices themselves. In your code, you initially place a pointer to values in positions val[0]. Then you modify values and then set a pointer to values in val[1]. But both val[0] and val[1] point to the same underlying object (values), which has been modified.

You can fix this by creating a new values slice on each iteration of the outer loop, this way each sub slice of val will be a different slice.

For example:

func main() {
    val := make([][]int, 2)
    for i:=0; i<2; i++ {
        values := make([]int, 0, 100)
        for j:=0; j<2; j++ {
            values = append(values, i+j)
        }
        val[i] = values
        fmt.Println(values, val) //
    }
    fmt.Println(val)
}

Output from fmt.Println:

[0 1] [[0 1] []]    // values, val
[1 2] [[0 1] [1 2]] // values, val
[[0 1] [1 2]]       // val

You should initialize values in your for loop, values = []int{}

code like this:

package main

import (
    "fmt"
)

func main() {
    var (
        valLength = 2
    )
    val := make([][]int, valLength)
    for i := 0; i < valLength; i++ {
        values := []int{}
        for j := 0; j < 2; j++ {
            values = append(values, i+j)
        }
        val[i] = values
        fmt.Println(values, val) //
    }
    fmt.Println(val)
}

And you only change variable valLength to get any length of slice you want.

slice feature in go:

Slices hold references to an underlying array, and if you assign one slice to another, both refer to the same array.

The value of slice will be the last time you modify it. Thus, here's two approach to achieve the goal.

use copy

func main() {
    values := make([]int, 0, 100)
    val := make([][]int, 2)
    for i := 0; i < 2; i++ {
        values = values[:0]
        for j := 0; j < 2; j++ {
            values = append(values, i+j)
        }
        val[i] = make([]int, 2)
        copy(val[i], values)
        fmt.Println(values, val) //
    }
    fmt.Println(val)
}

new values slice in first for-loop each time

val := make([][]int, 2)
for i := 0; i < 2; i++ {
    values := make([]int, 0, 2)
    for j := 0; j < 2; j++ {
        values = append(values, i+j)
    }
    val[i] = values
    fmt.Println(values, val) //
}