2016-07-14 8 views
5

Wenn ich ein Typ wie definiert haben:Wie klont man eine Struktur mit nicht exportiertem Feld?

type T struct { 
    S string 
    is []int 
} 

wie kann ich dann über das Klonen ein Objekt dieser Art gehen? Wenn ich eine einfache Zuordnung zu tun:

p := T{"some string", []int{10, 20}} 
q := p 

Dann werden alle Änderungen an den []int beide Objekte beeinflussen. Da T.is nicht exportiert wird, kann es nicht explizit kopiert werden, selbst wenn es mit reflect extrahiert wird.

Ich liefere derzeit eine Clone Methode im Paket des Typs selbst. Aber das hilft nicht mit ähnlichen Typen in anderen Paketen. Gibt es einen anderen Weg, dies zu tun?

Antwort

5

Sie können nicht. Das ist der Punkt der nicht exportierten Felder: Nur das Deklarationspaket kann sie modifizieren.

Beachten Sie, dass, wenn der T Typ in einem anderen Paket deklariert ist, kann man nicht einmal schreiben:

p := somepackage.T{"some string", []int{10, 20}} 

weil dies implizit das unexported T.is Feld zu setzen versuchen würde, und führt somit zu einem Kompilierzeitfehler :

implicit assignment of unexported field 'is' in somepackage.T literal 

Wenn Sie besitzen das Paket (oder Sie können ändern), ist am besten, eine Clone() Methode oder Funktion zur Verfügung zu stellen, oder ein SetIs() Verfahren zumTyp liefern 0. Wenn ein Paket eines Drittanbieters diese Funktionalität nicht bietet, können Sie nichts dagegen tun.

Beachten Sie, dass Paket mit unsafe es möglich ist, solche Dinge zu tun, aber wie der Name schon sagt: es ist unsicher und Sie sollten von ihm wegbleiben.

Beachten Sie auch, dass Sie neue Werte von T erstellen können, wo is nicht kopiert wird, sondern werden die zero value seine Art (die im Fall von []int wird nil sein) sein:

var r somepackage.T 
s := somepackage.T{S: p.S} 

fmt.Printf("%q\n", r) 
fmt.Printf("%q\n", s) 

Welche folgende Ausgabe:

{"" []} 
{"some string" []} 

Aber Sie T.is alle nicht-Null-Wert für das unexported Feld nicht einstellen.