2014-10-17 16 views
6

Acemi Go programcısı burada. Dilimlerin (ve temel dizinin bir kısmı) çoğaltılmasına ihtiyacım var, böylece bir arayanın bir dizinin orijinal öğelerini değiştirmemesi gerekir.Kopyalama için genel yol Git dilimleri?

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

Ama jenerik aynı yöntemi oluşturmak için bir yol belki jeneriği olmayan vardır: Ben belirli türleri dizileri için bunu yapmak için bir işlev yazabilirsiniz düşünüyorum? Bir dilim sığ bir kopyasını yapmak için basit bir açıklama yazabilirsiniz

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

cevap

20

,

eşdeğerdir
b := append([]T(nil), a...) 

Örneğin

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) 
} 

Çıkış:

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

EK:

Common difficulties with reflection

kişi Go yeni iseniz, bunlar hiç yansıma kullanarak olmamalıdır.

-Rob

Yansıma uzmanların bile ince olduğunu. anlayışı, dilin nasıl çalıştığını ve daha az ölçüde nasıl uygulandığına dair oldukça temel şeyleri bilmeye dayanan ayrıntıları açığa çıkarır. , deneyimli Go programcıları için bile şaşırtıcı olabilir; Yeni numaralı Gophers için, ilk olarak 'u öğrenmek için çok daha önemli, daha basit şeyler vardır. Çok erken yansımalarını öğrenenler, kendilerini bu temelleri anladıkları için bulutlarını karıştırırlar. Resmin kalan kısmı temizlenene kadar kolun uzunluğunda kalması en iyisidir.

-Rob söyledi

,

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) 
    } 

} 

Çıktı: Sen Özellikle reflect.Copy, reflect paketini kullanarak herhangi tipine bir kopyasını yapabilirsiniz

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

Yani özünde “a” unsurlarını “b” ye atanan yeni bir dizi için yeni, boş bir dilime ekliyorsunuz, değil mi? – Kaiged

+0

“append” yöntemi 'make' /' copy' yöntemiyle performans mıdır? – Kaiged

+0

@Kaiged: Bir "nil" diliminin eki bir "make" ve "copy" olarak çevrilir. Benim revize edilmiş cevabımı görün. – peterSO

İlgili konular