我对将切片传递给函数有疑问。
如果我没有错的话,切片在 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)
但是它需要遍历原始切片中的所有值来复制它们中的每一个,这似乎不是一个很好的解决方案。
有一个内置的功能,copy,func 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)
要将切片附加到另一个切片,请记住省略号 ( ...)。