2014-10-17 7 views
6

Anfänger Gehen Sie hier Programmierer. Ich muss Slices (und Teile des zugrunde liegenden Arrays) duplizieren, damit ein Aufrufer die ursprünglichen Elemente eines Arrays nicht mutiert. Ich glaube, ich kann eine Funktion schreiben, dies für Arrays von bestimmten Arten zu tun:Generische Möglichkeit, Go-Slices zu duplizieren?

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

Aber ist es eine Möglichkeit, die gleiche Methode generisch zu schaffen, vielleicht ohne Generika?

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

Antwort

20

Sie könnten eine einfache Erklärung schreiben eine flache Kopie einer Scheibe zu machen,

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

, die gleich ist,

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

Zum Beispiel

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

Ausgabe:

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

NACHTRAG:

Common difficulties with reflection

Wenn die Menschen neu zu gehen, sollten sie nicht überhaupt mit Reflexion sein.

-rob

Reflexion ist auch für Experten subtil. Es zeigt Details, deren Verständnis davon abhängt, ziemlich grundlegende Dinge darüber zu wissen, wie die Sprache funktioniert und in geringerem Maße, wie es implementiert wird. Es kann sogar für erfahrene Go-Programmierer verwirrend sein; für neu geprägte Gophers gibt es viel wichtigere, einfachere Dinge zu lernen zuerst. Diejenigen, die Reflexion zu früh lernen verwechseln sich selbst ihr Verständnis dieser Grundlagen. Am besten halten Sie es auf Arms Länge, bis der Rest des Bildes klar ist.

-ROB

Das heißt,

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

} 

Ausgang:

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

Sie fügen Elemente von 'a' also in ein neues, leeres Segment für ein neues Array hinzu, das' b' zugewiesen ist, oder? – Kaiged

+0

Ist die 'append' Methode so performant wie die' make'/'copy' Methode? – Kaiged

+0

@Kaiged: Das Anhängen an ein 'nil'-Segment wird in' make' und 'copy' übersetzt. Siehe meine überarbeitete Antwort. – peterSO

Verwandte Themen