2016-11-10 5 views
0

ich ein neues bin auf go.Now Ich habe eine Frage zu functoin variable.Here Pass ist der Code:golang andere func Änderung Karte eines struct

type User struct { 
    Name string 
    Map map[string]string 
} 
func main() { 
    u := User{Name: "Leto"} 
    u.Map = make(map[string]string) 
    fmt.Println("before --------") 
    fmt.Println(unsafe.Pointer(&u)) 
    fmt.Println(unsafe.Pointer(&(u.Map))) 
    fmt.Println(u) 
    Modify(u) 
    fmt.Println("after --------") 
    fmt.Println(u) 
} 
func Modify(u User) { 
    fmt.Println("in func --------") 
    fmt.Println(unsafe.Pointer(&u)) 
    fmt.Println(unsafe.Pointer(&(u.Map))) 
    u.Name = "Paul" 
    u.Map["t"] = "t" 
} 

Code oben Ausgang:

before -------- 
0xc04203a4c0 
0xc04203a4d0 
{Leto map[]} 
in func -------- 
0xc04203a500 
0xc04203a510 
after -------- 
{Leto map[t:t]} 

in Modify func ich weiß, Benutzer ist eine Kopie, so ändern Sie den Namen nicht funktionieren ist in Ordnung, aber warum Map-Effekt aus Benutzer struct ändern?

+0

Gibt es Gründe, 'unsafe' verwenden anstelle von' fmt.Printf ("% p \ n", & u) '? – nothingmuch

+0

Interessanterweise beantwortet @nothingmuch tatsächlich seine eigene Frage mit diesem Benutzernamen! –

+2

Da nur die ** Map ** ** selbst ** nach Wert übergeben (und kopiert) wird: Der ** Inhalt ** der Map wird von allen Kopien der Map gemeinsam genutzt. So verhält sich eine Karte - während sie formal kopiert und nach Wert übergeben wird - als wäre sie ein Referenztyp. – Volker

Antwort

0

Wir müssen verstehen, wie Speicherzuweisung in jedem Aufruf hier arbeitet:

u := User{Name: "Leto"} 
// u is an object of type User 
// after this line memory has been allocated to both the 
// properties u.Name(string) and u.Map(reference) 
// lets say allocated memory address for u.Name starts with x 
// for u.Map it starts with y, and note that u.Map is a reference i.e. 
// the value contained in it will be a different memory address which 
// will be the starting memory address of the actual map 
// right now the value written at y is nil since it 
// does not point to any memory address 
u.Map = make(map[string]string) 
// now value of y has been updated to z (which is the 
// memory address of the beginning of the map initialized 
// with make call) 
fmt.Println("before --------") 
fmt.Println(unsafe.Pointer(&u)) 
fmt.Println(unsafe.Pointer(&(u.Map))) 
fmt.Println(u) 
// here you are about to pass object by value 
// so basically a new object will be created of type User 
// lets talk about how copy of this object will be created 
// copy of u.Name will have a new address 
// lets call it x1 and the value "Leto" too will be 
// copied to memory address starting with x1 
// copy of u.Map will have a new address too lets call it 
// y1 and its value z will be copied too to the memory address y1 
// I think you must have got your answer by now. 
// Basically the newly copied object's property u.Map and 
// the old one's u.Map both points to the same memory address "z" 
// and hence whosoever updates the map the other one will see it 
Modify(u) 
fmt.Println("after --------") 
fmt.Println(u) 
+0

Thks, nette Antwort – user3819305

0

Slices, Karten und Kanäle sind Referenztypen. so werden sie immer als Referenz weitergegeben.

+0

danke! Ich habe es – user3819305

0

Sie sollten & Benutzer und * Benutzer jeweils in Ihren Zuweisungs- und Änderungsvorgängen verwenden.

Sehen Sie sich diese https://play.golang.org/p/tDh1JBpK-t

Es ist immer besser mit Zeigern zu arbeiten, um Structs.