【问题标题】:Golang slice append built-in function returning valueGolang slice append 内置函数返回值
【发布时间】:2017-02-21 03:36:32
【问题描述】:

这段代码slice2的返回值为[[1 1][1 1]]。
这让我很困惑,因为我期待 [[0 0][1 1]]。
我无法弄清楚为什么返回 [[1 1][1 1]] 而不是 [[0 0][1 1]]。
如果有人能解释一下,我将不胜感激。谢谢。

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

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

您可以查看此链接中的代码 play.golang.org

【问题讨论】:

    标签: go slice


    【解决方案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).

    在您的情况下,您附加的是切片(指针)而不是切片的值。要获得所需的结果,您必须在每次迭代中声明一个新切片并将新切片附加到切片 2。

    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

    【讨论】:

      【解决方案2】:

      当您在切片上进行范围时,它不会为您提供切片的值,而是为您提供索引。这个 for 循环相当于for i:=0; i < len(slice); i++ {}。因此,当它通过迭代时,slice 中的两个值都为 1,并且您已将其附加到 slice2 两次。

      如果您想要切片的值,则需要执行for i, v := range slice {},这将为您提供索引和值。如果您不想要索引,可以使用 _ 代替 i

      还要注意,像这样附加slice 两次会附加相同的确切切片,因为切片是作为堆上的指针分配的,因此它是指向切片的指针。因此 slice2[0] == slice2[1] 因为它是完全相同的切片。

      【讨论】:

      • 具体来说,slice 是一个具有 3 个字段的结构:指向底层数组的指针、容量和长度。由于您正在按索引更新切片的项目,因此您正在更改底层数组。由于您两次附加相同的切片,因此两者都引用相同的底层数组,因此更改第二个循环迭代中的值也会改变第一个切片的值。
      【解决方案3】:

      问题是您附加到slice2 的内容是对slice引用,而不是调用时slice 中包含的值。

      这意味着最后,slice2 包含两个指向同一个切片的指针。对slice 变量的任何更改都将反映到slice2,反之亦然:它们指向内存中的相同位置。

      作为证明,只需这样做:

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

      你会得到:

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

      【讨论】:

      • 感谢您的解释。现在一切都说得通了。
      猜你喜欢
      • 2021-08-28
      • 1970-01-01
      • 2018-06-25
      • 2017-11-12
      • 1970-01-01
      • 2014-09-03
      • 2016-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多