Nello snippet di codice seguente, mi piacerebbe capire cosa viene memorizzato esattamente in iPerson
quando il suo contenuto non è ancora inizializzato: solo un valore di 0-byte? O è in realtà un puntatore sotto il cofano (e anche inizializzato a 0-bytes ovviamente)? In ogni caso, cosa succede esattamente a iPerson = person
?In che modo vengono implementate le variabili dell'interfaccia in Go?
Se iPerson = person
esegue una copia di person
, cosa succede quando un oggetto che implementa IPerson
ma con un diverso footprint formato/memoria viene assegnato ad iPerson
? Capisco iPerson
è una variabile memorizzata nello stack, quindi la sua dimensione deve essere corretta. Ciò significa che l'heap è effettivamente utilizzato sotto il cofano, quindi iPerson
viene effettivamente implementato come puntatore, ma i compiti continuano a copiare l'oggetto, come dimostrato dal codice precedente? Ecco il codice:.
type Person struct{ name string }
type IPerson interface{}
func main() {
var person Person = Person{"John"}
var iPerson IPerson
fmt.Println(person) // => John
fmt.Println(iPerson) // => <nil> ...so looks like a pointer
iPerson = person // ...this seems to be making a copy
fmt.Println(iPerson) // => John
person.name = "Mike"
fmt.Println(person) // => Mike
fmt.Println(iPerson) // => John ...so looks like it wasn't a pointer,
// or at least something was definitely copied
}
(Questa domanda è il risultato di me avere ripensamenti sulla precisa di fatto correttezza della mia risposta a why runtime error on io.WriterString? Così ho deciso di provare a fare qualche indagine per capire come è esattamente questo variabili dell'interfaccia e le assegnazioni per farli lavorare in Go)
EDIT:. dopo aver ricevuto alcune risposte utili, io sono ancora perplesso con questo:
iPerson = person
iPerson = &person
- entrambi sono legali. Tuttavia, a mio avviso, ciò solleva la questione del perché il compilatore permetta di effettuare una digitazione così debole? Una conseguenza di quanto sopra è questo:
iPerson = &person
var person2 = iPerson.(Person) # panic: interface conversion: interface is *main.Person, not main.Person
che modifica la prima riga ripara:
iPerson = person
var person2 = iPerson.(Person) # OK
... quindi non è possibile determinare se staticamente iPerson
contiene un puntatore o un valore; e sembra che nulla possa assegnarne uno in fase di esecuzione senza errori. Perché è stata presa una tale decisione di progettazione? Quale scopo serve? Sicuramente non si adatta alla mentalità del "tipo sicurezza".
Quali sono gli enigmi per cui Go consente sia 'iPerson = & person' che' iPerson = person' senza dover cambiare il tipo di 'iPerson'. Consente errori di tipo runtime che potrebbero invece essere rilevati staticamente. È qualcosa che l'articolo segnalato da Volker non copre o menziona. –
Se si considera la struttura come un valore immutabile, potrebbe essere molto sensato passarla per valore. In pratica, probabilmente non li mescolerai se definisci i tuoi metodi per prendere un ricevitore puntatore, poiché quei metodi non saranno in grado di accedere al valore contenuto nel valore dell'interfaccia, quindi non saranno confusi: http: // play .golang.org/p/E_8WjLS4S0 –
OK, quindi stai dicendo che in pratica questo non sarà un problema? Ma continuerei a sostenere che questa è una ineleganza nella progettazione della lingua e che il sistema dei tipi potrebbe fare un lavoro migliore qui. –