如何将切片的副本传递给函数?

Kel*_*inS 4 go slice

我对将切片传递给函数有疑问。

如果我没有错的话,切片在 Go 中是通过引用传递的,所以如果我做这样的事情:

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5}
    fmt.Println(slice)
    testSlice(slice)
    fmt.Println(slice)
}

func testSlice(slice []int) {
    slice[0] = 5
    slice[4] = 1
}
Run Code Online (Sandbox Code Playgroud)

testSlice函数实际上会更改原始切片中的值,因为它是通过引用传递的(默认情况下)。

有一些简单的方法可以直接将切片的副本传递给testSlice函数吗?

当然我可以做这样的事情来创建切片的副本:

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5}
    fmt.Println(slice)
    testSlice(slice)
    fmt.Println(slice)
}

func testSlice(slice []int) {
    var newSlice []int
    for i := 0; i < len(slice); i++ {
        newSlice = append(newSlice, slice[i])
    }
    newSlice[0] = 5
    newSlice[4] = 1
}
Run Code Online (Sandbox Code Playgroud)

但是它需要遍历原始切片中的所有值来复制它们中的每一个,这似乎不是一个很好的解决方案。

Nev*_*ore 7

有一个内置的功能,copyfunc copy(dst, src []T) int这可能是你在找什么。它将任何类型的切片复制到另一个切片中。

文档

复制功能支持在不同长度的切片之间进行复制(它只会复制到较少数量的元素)。此外,复制可以处理共享相同底层数组的源和目标切片,正确处理重叠的切片。

所以

list := []string{"hello", "world"}
newList := make([]string, len(list))
n := copy(newList, list)
// n is the number of values copied
Run Code Online (Sandbox Code Playgroud)

将复制list到一个新的 slice 中newList,该slice共享值但不共享内存中的引用。所述int copy返回是复制的值的数目。


对于另一种方式,根据 Kostix 的评论,您可以将切片附加到空切片。这有点像复制它。它可能不是惯用的,但它允许您将切片func作为副本传递到 a中,有点像. 如果您这样做,我建议您发表大量评论。

thisFuncTakesSliceCopy( append([]string(nil), list...) )
Run Code Online (Sandbox Code Playgroud)

要将切片附加到另一个切片,请记住省略号 ( ...)。

  • 也可以执行 `b := append([]byte(nil), a...)` 将整个 `a` 附加到一个 nil 切片——本质上是生成一个分配给 `b` 的副本。 (2认同)