为什么我不能在golang中拷贝一份拷贝?

我需要做一个切片的副本去阅读文档有一个复制function在我的处置。

复制内置函数将来自源片段的元素复制到目标片段中。 (作为特殊情况,它也会将字节中的字节复制到一个字节片段中。)源和目标可能会重叠。 复制返回复制的元素的数量,这将是len(src)和len(dst)的最小值。

但是当我这样做

arr := []int{1, 2, 3} tmp := []int{} copy(tmp, arr) fmt.Println(tmp) fmt.Println(arr) 

我的tmp是空的,因为它以前(我甚至试图使用arr,tmp):

 [] [1 2 3] 

你可以去操场上检查它。 那么为什么我不能复制一个切片?

内置copy(dst, src)拷贝min(len(dst), len(src))元素。

所以如果你的dst是空的( len(dst) == 0 ),什么都不会被复制。

尝试tmp := make([]int, len(arr)) ( Go Playground ):

 arr := []int{1, 2, 3} tmp := make([]int, len(arr)) copy(tmp, arr) fmt.Println(tmp) fmt.Println(arr) 

产量(如预期):

 [1 2 3] [1 2 3] 

不幸的是,这在builtin包中没有logging,但是在Go语言规范中有logging:追加和复制片

复制元素的数量是len(src)len(dst)的最小值。

编辑:

最后, copy()的文档已经更新了,现在它包含了一个事实,即源和目标的最小长度将被复制:

复制返回复制的元素的数量,这将是len(src)和len(dst)的最小值

如果您的切片尺寸相同, 则可以工作 :

 arr := []int{1, 2, 3} tmp := []int{0, 0, 0} i := copy(tmp, arr) fmt.Println(i) fmt.Println(tmp) fmt.Println(arr) 

会给:

 3 [1 2 3] [1 2 3] 

从“ 切片:使用和内部 ”:

复制function支持在不同长度的片段之间进行复制( 它只复制到less量的元素

通常的例子是:

 t := make([]byte, len(s), (cap(s)+1)*2) copy(t, s) s = t 

另一个简单的方法是使用append来分配进程中的slice。

 arr := []int{1, 2, 3} tmp := []int{} tmp = append(tmp, arr...) // Notice the ... splat fmt.Println(tmp) fmt.Println(arr) 

产量(如预期):

 [1 2 3] [1 2 3] 

所以复制数组arr的简写为tmp := append([]int{}, arr...)

https://play.golang.org/p/sr_4ofs5GW

copy()运行dst和src的最小长度,所以你必须初始化dst到所需的长度。

 A := []int{1, 2, 3} B := make([]int, 3) copy(B, A) C := make([]int, 2) copy(C, A) fmt.Println(A, B, C) 

输出:

 [1 2 3] [1 2 3] [1 2] 

您可以使用append()将所有元素初始化并复制到一个无切片中。

 x := append([]T{}, []...) 

例:

 A := []int{1, 2, 3} B := append([]int{}, A...) C := append([]int{}, A[:2]...) fmt.Println(A, B, C) 

输出:

 [1 2 3] [1 2 3] [1 2] 

与分配+ copy()相比,对于大于1,000个元素,使用append。 其实低于1000的差别可能会被忽略,除非你有很多的切片,否则就是一个经验法则。

 BenchmarkCopy1-4 50000000 27.0 ns/op BenchmarkCopy10-4 30000000 53.3 ns/op BenchmarkCopy100-4 10000000 229 ns/op BenchmarkCopy1000-4 1000000 1942 ns/op BenchmarkCopy10000-4 100000 18009 ns/op BenchmarkCopy100000-4 10000 220113 ns/op BenchmarkCopy1000000-4 1000 2028157 ns/op BenchmarkCopy10000000-4 100 15323924 ns/op BenchmarkCopy100000000-4 1 1200488116 ns/op BenchmarkAppend1-4 50000000 34.2 ns/op BenchmarkAppend10-4 20000000 60.0 ns/op BenchmarkAppend100-4 5000000 240 ns/op BenchmarkAppend1000-4 1000000 1832 ns/op BenchmarkAppend10000-4 100000 13378 ns/op BenchmarkAppend100000-4 10000 142397 ns/op BenchmarkAppend1000000-4 2000 1053891 ns/op BenchmarkAppend10000000-4 200 9500541 ns/op BenchmarkAppend100000000-4 20 176361861 ns/op 

Go编程语言规范

追加和复制切片

函数拷贝将slice元素从源src复制到目标dst,并返回复制元素的数量。 两个参数必须具有相同的元素typesT,并且必须可分配给types为[] T的片段。 复制元素的数量是len(src)和len(dst)的最小值。 作为一种特殊情况,copy也接受一个可指派给types为[] byte的目标参数,并使用一个stringtypes的源参数。 这种forms将string中的字节复制到字节片段中。

 copy(dst, src []T) int copy(dst []byte, src string) int 

tmp需要足够的空间来存放arr 。 例如,

 package main import "fmt" func main() { arr := []int{1, 2, 3} tmp := make([]int, len(arr)) copy(tmp, arr) fmt.Println(tmp) fmt.Println(arr) } 

输出:

 [1 2 3] [1 2 3]