英文:
How to pass a copy of a slice to a function?
问题
我对将切片传递给函数有些疑问。
如果我没记错的话,在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
}
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
}
但这需要遍历原始切片的所有值来复制它们,而且似乎不是一个很好的解决方案。
英文:
I have a doubt about passing slices to functions.
If I'm not wrong the slices are passed by reference in Go, so if I do something like this:
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
}
The testSlice
function will actually change the values in the original slice, because it was passed by reference (by default).
There is some easy way that I can directly pass a copy of the slice to the testSlice
function?
Sure I can do something like this to create a copy of the slice:
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
}
But it needs to go through all values in the original slice to copy each of them, and it doesn't seem to be a great solution.
答案1
得分: 11
有一个内置函数copy
,func copy(dst, src []T) int
,这可能是你要找的。它可以将一个任意类型的切片复制到另一个切片中。
根据文档:
copy
函数支持在不同长度的切片之间进行复制(它只会复制最小数量的元素)。此外,copy
可以处理共享相同底层数组的源切片和目标切片,正确处理重叠的切片。
所以
list := []string{"hello", "world"}
newList := make([]string, len(list))
n := copy(newList, list)
// n 是复制的值的数量
将会把list
复制到一个新的切片newList
中,它们共享值但在内存中的引用不同。copy
返回的int
是复制的值的数量。
另一种方法是根据Kostix的评论,你可以将切片追加到一个空切片中。这有点像复制它。这可能不是惯用的写法,但它允许你将切片作为副本传递给一个func
。如果你这样做,我建议写上详细的注释。
thisFuncTakesSliceCopy(append([]string(nil), list...))
要将一个切片追加到另一个切片中,记得使用省略号(...
)。
英文:
There is a built in function, copy
, func copy(dst, src []T) int
which is probably what you're looking for. It copies a slice of any type into another slice.
From the docs:
> The copy function supports copying between slices of different lengths (it will copy only up to the smaller number of elements). In addition, copy can handle source and destination slices that share the same underlying array, handling overlapping slices correctly.
So
list := []string{"hello", "world"}
newList := make([]string, len(list))
n := copy(newList, list)
// n is the number of values copied
Will copy list
into a new slice newList
, which share values but not the reference in memory. The int
copy
returns is the number of values copied.
<hr>
For an alternative way, from Kostix's comment, you can append the slice to an empty slice. Which is kind of like copying it. It might not be idiomatic, but it allows you to pass the slice into a func
as a copy, sort of. If you do this, I recommend copious comments.
thisFuncTakesSliceCopy( append([]string(nil), list...) )
To append a slice to another slice, remember the ellipses (...
).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论