2017-09-20 2 views
1

Ich versuche, in a := b um herauszufinden, ob a eine andere Kopie von structWarum haben alle verschachtelten Strukturobjekte beim Ausdruck dieselbe Adresse?

wie func pass_by_value(a some_struct) sein wird, aber ich finde, dass ich die print-Anweisung nicht verstehen.

Betrachten Sie diese go playground

nested_level2 := test_assign_nested_level2{} 
    nested_level1 := test_assign_nested{nested_level2} 
    top_level := test_assign{nested_level1} 

    assign := top_level 
    fmt.Println("top_level address") 
    fmt.Printf("%p", &top_level) 
    fmt.Println(" ") 
    fmt.Println("1 level address") 
    fmt.Printf("%p", &top_level.Level1) 
    fmt.Println(" ") 
    fmt.Println("2 level address") 
    fmt.Printf("%p", &top_level.Level1.Level_2) 
    fmt.Println("------------------------") 

    fmt.Println("assign top_level address") 
    fmt.Printf("%p", &assign) 
    fmt.Println(" ") 
    fmt.Println("1 level address") 
    fmt.Printf("%p", &assign.Level1) 
    fmt.Println(" ") 
    fmt.Println("2 level address") 
    fmt.Printf("%p", &assign.Level1.Level_2) 

Der Ausgang des oben

ist
top_level address 
0x10410020 
1 level address 
0x10410020 
2 level address 
0x10410020 
assign top_level address 
0x10410024 
1 level address 
0x10410024 
2 level address 
0x10410024 

ich die Ausgabe erwarten ähnlich sein

fmt.Println("top_level address") 
    fmt.Printf("%p", &top_level) 
    fmt.Println(" ") 
    fmt.Println("1 level address") 
    fmt.Printf("%p", &nested_level1) 
    fmt.Println(" ") 
    fmt.Println("2 level address") 
    fmt.Printf("%p", &nested_level2) 
    fmt.Println(" ") 
    fmt.Println(" ------------------------------- ") 

wo

top_level address 
0x421152280 
1 level address 
0x421152270 
2 level address 
0x421152260 

Jede Struktur hat eine andere Adresse. aber es scheint, dass die Child-Struktur die gleiche Adresse wie die Eltern-Struktur hat.

Warum hat das gesamte verschachtelte Element in der Struktur die gleiche Adresse?

Und kopiert tatsächlich := eine neue struct rekursiv? Wie die Print-Anweisung angezeigt? (. Dh := wird eine brandneue Kopie Struktur mit jedem seiner Feldinhalt zurückgeben auch eine brandneue Kopie rekursiv)

+3

Alle Zuweisungen in Go sind Kopien. Die Adressen sind gleich, weil Sie jedes Mal die Adresse des gleichen Wertes nehmen. Experimentieren Sie mit dem Einfügen einiger anderer Werte in diese Strukturen. – JimB

+0

Ich versuche 6 verschiedene Werte zu drucken, Adresse von 'top_level', Adresse von' top_level. Level1 '' top_level.Level1.Level_2' etc ..... Kannst du erklären, warum sie alle gleich sind? – user3591466

+0

Obwohl assign: = top_level, hat assign einen eigenen Speicherplatz im Speicher, der sich von top_level unterscheidet, da es sich um eine neue Zuweisung handelt. Jede Referenz desselben Ortes wird denselben Ort zurückgeben. – Godfrey

Antwort

1

Meine Vermutung ist, dass Sie suchen nach etwas wie folgt aus:

package main 

import "fmt" 

// Nesting: type T2 struct{ F3 int } 
type T2 struct{ F3 int } 

// Nesting: type T1 struct{ { F2 struct{ F3 int } } 
type T1 struct{ F2 T2 } 

// Nesting: type T0 struct{ F1 struct{ F2 struct{ F3 int } } } 
type T0 struct{ F1 T1 } 

func main() { 
    t2 := T2{F3: 42} 
    fmt.Printf(
     "%p %p %d\n", 
     // 0xc4200120d0 0xc4200120d0 42 
     &t2, &t2.F3, t2.F3, 
    ) 

    t1 := T1{F2: t2} 
    fmt.Printf(
     "%p %p %p %d\n", 
     // 0xc4200120f0 0xc4200120f0 0xc4200120f0 42 
     &t1, &t1.F2, &t1.F2.F3, t1.F2.F3, 
    ) 

    t0 := T0{F1: t1} 
    fmt.Printf(
     "%p %p %p %p %d\n", 
     // 0xc420012100 0xc420012100 0xc420012100 0xc420012100 42 
     &t0, &t0.F1, &t0.F1.F2, &t0.F1.F2.F3, t0.F1.F2.F3, 
    ) 
} 

Ausgang:

0xc4200120d0 0xc4200120d0 42 
0xc4200120f0 0xc4200120f0 0xc4200120f0 42 
0xc420012100 0xc420012100 0xc420012100 0xc420012100 42 

Für T0

type T0 struct{ F1 T1 } 

type T1 struct{ F2 T2 } 

type T2 struct{ F3 int } 

entspricht

type T0 struct { 
    F1 struct { 
     F2 struct { 
      F3 int 
     } 
    } 
} 

und T0, F1, F2 und F3 die gleiche Adresse haben.


In Ihrem neuen Beispiel ist T0

type T2 struct{ F3A, F3B int } 

type T1 struct{ F2 T2 } 

type T0 struct{ F1 T1 } 

entspricht

type T0 struct { 
    F1 struct { 
     F2 struct { 
      F3A int 
      F3B int 
     } 
    } 
} 

und T0, F1, F2 und F3A die gleiche Adresse haben. F3A und F3B haben unterschiedliche Adressen.

+0

Sorry, ich bin immer noch verwirrt, warum haben sie alle die gleiche Adresse? Und warum existiert das gleiche Adressverhalten nur für das erste Feld der Struktur wie in [this playground] (https://play.golang.org/p/rA-sx__j7d)? – user3591466

2

Typen in Go sind keine autonomen Wrapper um andere Dinge, sondern nur zwei Dinge: Typen ermöglichen das Anhängen von Methoden und Typen bieten ein Layout im Speicher. Für die Frage hier ist die Fähigkeit, Methoden an Typen anzuhängen, irrelevant.Werfen wir einen Blick eine neutrale Formulierung der Frage nehmen:

type A int64 
type B { a A } 
type C { b B } 

Dies erklärt drei Typen mit folgendem Speicherlayout:

  • Typ A hat das Speicherlayout eines int64 (dh 8 Byte).
  • Typ B hat das Speicherlayout eines einzelnen A, das ist ein int64, also 8 Bytes.
  • Typ C hat das Speicherlayout eines einzelnen B, das ist ein einzelnes A, das ist ein int64, also 8 Bytes.

Typ B Speicherlayout in Bezug ist nicht ein "Wrapper" um A, zumindest die Verpackung absolut nichts hinzufügt. Aus einer reinen Speicherlayoutperspektive wäre das Definieren von Typ B nutzlos (aber es erlaubt, verschiedene Methoden an B anzuhängen als an A).

Jetzt sollte klar sein, dass die Adresse eines c C ist, dass der erste seiner 8 Bytes und das ist die gleiche wie c.b Adresse, die die gleiche ist als c.b.a. Und jede Zuweisung zu einem C ist nur eine Kopie eines Maschinenworts (auf 64-Bit-Architekturen).

Wenn Sie type D { a A; b B } definieren, wird es interessanter, da ein D jetzt 16 Byte lang ist. (Das Hinzufügen von mehr zu einem D könnte sogar Löcher aufgrund von Auffüllung hinterlassen.) Aber immer noch liefert D nichts (erwarte einen neuen Methodensatz) an ein A und ein B, die nebeneinander im Speicher sind.

Verwandte Themen