2014-10-17 72 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