【问题标题】:Slice copy mutating original slice切片复制变异原始切片
【发布时间】:2021-10-28 03:47:03
【问题描述】:

有人可以帮助解释为什么这段代码会改变原始数组 a 的 Golang 内部原理吗?

func main() {
    a := []int{1,2,3,4}
    b := a
    b = append(b[0:1], b[2:]...)
    fmt.Println(b)
    fmt.Println(a)
}

输出:

[1 3 4]
[1 3 4 4]

我认为b := a 会按值传递。提前致谢。

【问题讨论】:

标签: go slice


【解决方案1】:

这就是切片的工作原理。切片只是一个指针(+大小+容量),实际数据存储在数组中。

复制切片时,不会复制底层数组。然后你会得到两个指向同一个数组的切片。改变一个切片的值将通过另一个切片变得可见。

更多详情请见Go Slices: usage and internals

如果您想保持原始切片不变,请先创建一个deep copy。比如这样的

    b := append([]int{}, a...)  // deep copy

(Live demo)

【讨论】:

    【解决方案2】:

    切片基本上是数组的包装。切片没有自己的数据,它们只是保存对数组的引用。在您给定的代码中,您将 a 分配给 b 现在它们都表示相同的数组。因此,当您对切片 b 进行变异时,切片 a 也会发生变异。

    您可以使用copy 方法将元素从一个数组复制到另一个数组。

    // copy returns the count of total copied elements
    count := copy(b /*destination*/ , a /*source*/)
    

    但要确保分配一个与源数组长度相同的数组。 示例如下:

    func main() {
        a := []int{1,2,3,4}
        b := make([]int, len(a))
    
        _ = copy(b, a)
    
        a[0] = 2
    
        fmt.Println(b)
        fmt.Println(a)
    }
    

    【讨论】:

      猜你喜欢
      • 2019-09-29
      • 2021-10-26
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2018-08-31
      • 2011-06-13
      • 1970-01-01
      • 2014-10-22
      相关资源
      最近更新 更多