2016-07-14 49 views
5

Se ho un tipo definito come:Come clonare una struttura con campo non esportato?

type T struct { 
    S string 
    is []int 
} 

allora come posso fare per la clonazione di un oggetto di questo tipo? Se faccio una semplice assegnazione:

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

Poi tutte le modifiche apportate al []int effetto entrambi gli oggetti. Dal momento che T.is non viene esportato, non può essere copiato esplicitamente, anche se estratto utilizzando reflect.

Attualmente sto fornendo un metodo Clone nel pacchetto del tipo stesso. Ma questo non aiuta con tipi simili in altri pacchetti. c'è un altro modo per fare ciò?

risposta

5

Non è possibile. Questo è il punto dei campi non esportati: solo il pacchetto di dichiarazione può modificarli.

Si noti che se il tipo T è dichiarata in un altro pacchetto, non si può nemmeno scrivere:

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

perché ciò implicitamente cercare di impostare il campo T.is quali no e, quindi, si traduce in un errore di compilazione :

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

Se siete il proprietario (o si può modificare) il pacchetto, migliore è quello di fornire un metodo o una funzione Clone(), o di fornire un metodo per il tipo di SetIs()T. Se un pacchetto di terze parti non fornisce tale funzionalità, non c'è nulla che tu possa fare al riguardo.

noti che usare pacchetto unsafe è possibile fare queste cose, ma come dice il nome: è pericoloso e si dovrebbe stare lontano da esso.

Si noti inoltre che è possibile creare nuovi valori di T dove is non viene copiato ma sarà la zero value di questo tipo (che in caso di []int sarà nil):

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

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

che sarà in uscita:

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

Ma non si può impostare qualsiasi valore diverso da zero per il campo da non esportare T.is.

Problemi correlati