2017-05-11 2 views
0

ich seltsames Verhalten im folgenden Code sehe:Golang Struktur bekommt anderen Wert vom Eingang

type A struct { 
    D []int8 
} 

func main() { 
    a := A{D: make([]int8, 0)} 
    a.D = append(a.D, 0) 

    b := a 
    c := a 
    b.D = append(b.D, 1) 
    c.D = append(c.D, 2) 
    fmt.Println(a.D, b.D, c.D) 
} 

Ich Ausgabe

[0] [0 1] [0 2] 

Allerdings habe ich

[0] [0 2] [0 2] 
zu erwarten

Wer weiß warum ...?

p.s. Wenn ich die Zeile "a.D = append (a.D, 0)" auskommentiere oder den Typ von D von "[] ​​int8" zu "[] int" ändere, habe ich bekommen, was ich erwartet habe. Seltsam ...

+1

So viele Duplikate dieser Frage. Informieren Sie sich über Go und Zeiger. Ich habe gerade eine Frage ähnlich wie vor ein paar Stunden beantwortet. Sehen Sie dieses Beispiel https://play.golang.org/p/ZThHrP0pds und lesen Sie meine Antwort auf diese Frage. http://stackoverflow.com/questions/43922965/i-cannot-modified-the-item-after-appending-to-array Ich werde ein gutes Duplikat aufspüren, um dies zu verknüpfen. – RayfenWindspear

+0

Mögliches Duplikat [Go Variablen überschrieben werden (Bug?)] (Http://stackoverflow.com/questions/20277305/go-variables-being-overwritten-bug) – RayfenWindspear

Antwort

4

Zunächst einmal, den Typ zu ändern es nicht behoben werden: https://play.golang.org/p/fHX3JAtfNz

Was hier passiert hat mit der Mechanik von append und Referenztypen zu tun.

Grundsätzlich sind alle drei Strukturen an der gleichen zugrundeliegenden Array weisen, aber jede Scheibe ihren eigenen einzigartigen Längenargument hat.

Also, wenn Sie 1 an b anhängen, ist es [0 1] mit einer Länge von 2. c ist immer noch [0] mit einer Länge von 1. Sie fügen dann 2 an c an, machen es [0 2] mit eine Länge von 2. Sie ändern versehentlich auch den zweiten Wert des Arrays in b. Wenn Sie die Länge von a ohne append ändern könnten, wäre es auch [0 2].

Sinn machen? Zeiger und Scheiben sind komisch. Ganzer Artikel hier: https://blog.golang.org/slices

+0

Scheiben speziell seltsam ist. Zeiger in Go sind erstaunlich, aber wenn Sie nicht wissen, dass Go pass-by-value ist, können Sie sich entsetzen. – RayfenWindspear

+0

Pedantisch vielleicht, aber irgendetwas in Go einen "Referenztyp" zu nennen, ist irreführend und kann zu einigen Missverständnissen über gängiges Go-Verhalten führen. Als Referenz: https://dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go – Adrian

+0

Eh, _types_ kann "Referenztypen" in Go sein. Es ist nur, dass nichts als Referenz weitergegeben wird. Slices sind inhärent Referenzen, ebenso wie Karten, Kanäle und einige andere Primitive. Wenn sie übergeben werden, sind die Variablen selbst noch Kopien (dh Sie erhalten eine neue Version des Slice-Headers, und alle Änderungen an diesem Slice-Header (wie Länge oder die Adresse des zugrunde liegenden Arrays) propagieren nicht), sondern die zugrunde liegenden Daten referenzierte kann immer noch dieses "Pass-by-Reference" -Typ-Verhalten sehen. – Kaedys

Verwandte Themen