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

huangapple go评论67阅读模式
英文:

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 &quot;fmt&quot;

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 &quot;fmt&quot;

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 &lt; 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

有一个内置函数copyfunc 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{&quot;hello&quot;, &quot;world&quot;}
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 (...).

huangapple
  • 本文由 发表于 2017年4月21日 23:36:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/43546742.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定