Im folgenden Codefragment möchte ich verstehen, was genau in iPerson
gespeichert wird, wenn der Inhalt noch nicht initialisiert ist: nur ein Wert von 0 Bytes? Oder ist es eigentlich ein Zeiger unter der Haube (und natürlich auch auf 0 Bytes initialisiert)? Was passiert genau unter iPerson = person
?Wie genau sind Interface-Variablen in Go implementiert?
Wenn iPerson = person
macht eine Kopie von person
, was dann geschieht, wenn ein Objekt der Umsetzung IPerson
aber mit einem anderen Größe/Speicher-Footprint zu iPerson
zugewiesen wird? Ich verstehe, iPerson
ist eine Variable auf dem Stapel gespeichert, so muss seine Größe festgelegt werden. Bedeutet das, dass der Heap tatsächlich unter der Haube verwendet wird, also wird iPerson
tatsächlich als ein Zeiger implementiert, aber Zuweisungen kopieren immer noch das Objekt, wie durch den obigen Code demonstriert? Hier ist der Code:.
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
}
(Diese Frage ist das Ergebnis von mir zweite Gedanken über die genaue sachliche Richtigkeit meiner Antwort auf why runtime error on io.WriterString? mit Also habe ich einige Untersuchungen zu tun, um zu verstehen, um zu versuchen, entschieden, wie es ist genau das, Interface-Variablen und Zuweisungen, um sie in Go arbeiten)
EDIT:. nach ein paar nützliche Antworten erhalten zu haben, ich bin immer noch verwirrt mit diesem:
iPerson = person
iPerson = &person
-both sind legal. Für mich wirft dies jedoch die Frage auf, warum der Compiler eine solche schwache Typisierung erlaubt. Eine Folge der oben genannten ist dies:
iPerson = &person
var person2 = iPerson.(Person) # panic: interface conversion: interface is *main.Person, not main.Person
während die erste Zeile zu ändern fixiert es:
iPerson = person
var person2 = iPerson.(Person) # OK
... so ist es nicht möglich ist, statisch, um zu bestimmen, ob iPerson
hält einen Zeiger oder einen Wert; und es scheint, dass irgendjemand ihm zur Laufzeit einen ohne Fehler zuweisen kann. Warum wurde eine solche Designentscheidung getroffen? Welchen Zweck erfüllt es? Es passt definitiv nicht in die "type safety" Denkweise.
Was mich verwirrt ist, warum Go sowohl iPerson = & Person als auch iPerson = Person erlaubt, ohne den Typ von iPerson ändern zu müssen. Es erlaubt Laufzeitfehler, die stattdessen statisch abgefangen werden könnten. Es ist etwas, was der Artikel, auf den Volker hingewiesen hat, nicht behandelt oder erwähnt. –
Wenn Sie die Struktur als unveränderlichen Wert behandeln, kann es sinnvoll sein, sie nach Wert zu übergeben. In der Praxis werden Sie sie wahrscheinlich nicht verwechseln, wenn Sie Ihre Methoden so definieren, dass sie einen Zeigerempfänger verwenden, da diese Methoden nicht auf den Wert innerhalb des Schnittstellenwerts zugreifen können, so dass sie nicht verwechselt werden: http: // play .golang.org/p/E_8WjLS4S0 –
OK, du sagst also, dass das in der Praxis kein Problem sein wird? Aber ich würde immer noch argumentieren, dass dies ein Mangel an Eleganz im Sprachdesign ist und das Typsystem könnte hier einen besseren Job machen. –