2017-04-21 31 views
1

我只是在学习转到我对将slices传递给函数有疑问。如何将切片的副本传递给函数?

如果我没看错的slices通过引用围棋过去了,所以如果我做这样的事情:

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功能实际上将改变原来的slice的值,因为它通过引用传递(默认情况下)。

有一些简单的方法,我可以直接将slice的副本传递给testSlice函数?

当然,我可以做这样的事情来创建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 
} 

但它需要经过所有的值在原slice复制他们每个人,它似乎并不成为一个很好的解决方案。

回答

2

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

docs

复制功能支持不同长度的片段之间的复制(它将仅复制到元件的较小的数)。另外,复制可以处理共享相同基础阵列的源片和目标片,并正确处理重叠片。

所以

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

将复制list到一个新的片newList,其份额值,但不是在存储器中的参考。 intcopy返回值是复制值的数量。


对于另一种方式,从Kostix的评论,你可以追加切片到一个空的切片。这有点像复制它。它可能不是惯用的,但它允许您将片段传递到func作为副本,类型的。如果你这样做,我建议大量的意见。

thisFuncTakesSliceCopy(append([]string(nil), list...)) 

到切片追加到另一个切片,记得省略号(...)。

+0

谢谢@Nevermore,这是一个更优雅的方式来复制'切片'。只想确认一下。我无法直接将'slice'拷贝传递给一个函数?唯一的方法是手动创建一个新的“切片”并复制原始“切片”中的值?我只是问它,因为我来自'C++',在那里我可以通过引用或值传递向量。 – KelvinS

+0

@KelvinSalton去绝对没有“通过参考”的概念。一切都通过价值传递。切片是一个底层数组的描述符。如果您想要数组的那部分副本,则必须复制副本。Go的焦点不是“优雅”或“语法糖”,而是“明确的”: – Volker

+0

谢谢@Volker,现在更清晰了。 – KelvinS