2014-10-17 111 views
6

初学者Go程序员在这里。我需要复制切片(以及底层数组的一部分),因此调用者不会改变数组的原始元素。我想我可以写一个函数来为特定类型的数组做到这一点:复制Go切片的通用方法?

func duplicateSliceOfSomeType(sliceOfSomeType []SomeType) []SomeType { 
    dulicate := make([]SomeType, len(sliceOfSomeType)) 
    copy(duplicate, sliceOfSomeType) 
    return duplicate 
} 

但是,有没有办法一般产生相同的方法,也许没有泛型?

func duplicateSlice(slice []?) []?{ 
    duplicate := make([]?, len(slice)) 
    copy(duplicate, slice) 
    return duplicate 
} 

回答

20

你可以写一个简单的语句,使切片的浅拷贝,

b := append([]T(nil), a...) 

即相当于,

b := make([]T, len(a)) 
copy(b, a) 

例如,

package main 

import "fmt" 

type T int 

func main() { 
    a := []T{4, 2} 

    b := append([]T(nil), a...) 

    fmt.Println(&a[0], a, &b[0], b) 
    b[0] = 9 
    fmt.Println(&a[0], a, &b[0], b) 
} 

输出:

0x10328000 [4 2] 0x10328020 [4 2] 
0x10328000 [4 2] 0x10328020 [9 2] 

附录:

Common difficulties with reflection

如果人们新去的,他们不应该使用反射的。

-rob

即使对于专家来说,反射也是微妙的。它公开了一些细节,他们的理解依赖于了解语言如何工作以及在较小程度上如何实现语言的基本知识。即使对于有经验的Go程序员来说,它也可能令人迷惑不解。对于最近 铸造Gophers有更重要,更简单的事情首先学习 。那些反思过早的人会迷惑自己对这些基本面的理解。最好保持在手臂的 长度,直到图片的其余部分清晰。

-Rob

这就是说,

package main 

import (
    "fmt" 
    "reflect" 
) 

func CopySlice(s interface{}) interface{} { 
    t, v := reflect.TypeOf(s), reflect.ValueOf(s) 
    c := reflect.MakeSlice(t, v.Len(), v.Len()) 
    reflect.Copy(c, v) 
    return c.Interface() 
} 

type T int 

func main() { 

    { 
     // append 
     a := []T{4, 2} 
     b := append([]T(nil), a...) 
     fmt.Println(&a[0], a, &b[0], b) 
     b[0] = 9 
     fmt.Println(&a[0], a, &b[0], b) 
    } 

    { 
     // make and copy 
     a := []T{4, 2} 
     b := make([]T, len(a)) 
     copy(b, a) 
     fmt.Println(&a[0], a, &b[0], b) 
     b[0] = 9 
     fmt.Println(&a[0], a, &b[0], b) 
    } 

    { 
     // reflection 
     a := []T{4, 2} 
     b := CopySlice(a).([]T) 
     fmt.Println(&a[0], a, &b[0], b) 
     b[0] = 9 
     fmt.Println(&a[0], a, &b[0], b) 
    } 

} 

输出:

0xc20800a200 [4 2] 0xc20800a210 [4 2] 
0xc20800a200 [4 2] 0xc20800a210 [9 2] 
0xc20800a290 [4 2] 0xc20800a2a0 [4 2] 
0xc20800a290 [4 2] 0xc20800a2a0 [9 2] 
0xc20800a310 [4 2] 0xc20800a320 [4 2] 
0xc20800a310 [4 2] 0xc20800a320 [9 2] 
+0

因此,本质上,您将'a'的元素添加到分配给'b'的新阵列的新空片段中,对吗? – Kaiged 2014-10-17 20:58:03

+0

'append'方法与'make' /'copy'方法一样吗? – Kaiged 2014-10-17 21:17:24

+0

@Kaiged:对“无”片段的附加转换为“make”和“copy”。看到我修改后的答案。 – peterSO 2014-10-17 21:19:40