2016-07-18 32 views
5

Dlaczego, kiedy odwołujemy się do struct używając (* structObj), golang wydaje się zwracać nową kopię structObj niż zwracać ten sam adres oryginalnego structObj? Może być trochę nie rozumieją mój na ten temat, więc szukać rodzaju wyjaśnieńjest dereference golang struct return new copy of struct?

package main 

import (
    "fmt" 
) 

type me struct { 
    color string 
    total int 
} 

func study() *me { 
    p := me{} 
    p.color = "tomato" 
    fmt.Printf("%p\n", &p.color) 
    return &p 
} 

func main() { 


    p := study() 
    fmt.Printf("&p.color = %p\n", &p.color) 

    obj := *p 
    fmt.Printf("&obj.color = %p\n", &obj.color) 
    fmt.Printf("obj = %+v\n", obj) 

    p.color = "purple" 
    fmt.Printf("p.color = %p\n", &p.color) 
    fmt.Printf("p = %+v\n", p) 
    fmt.Printf("obj = %+v\n", obj) 

    obj2 := *p 
    fmt.Printf("obj2 = %+v\n", obj2) 
} 

Wyjście

0x10434120 
&p.color = 0x10434120 
&obj.color = 0x10434140 //different than &p.color! 
obj = {color:tomato total:0} 
p.color = 0x10434120 
p = &{color:purple total:0} 
obj = {color:tomato total:0} 
obj2 = {color:purple total:0} // we get purple now when dereference again 

golang playground

Odpowiedz

2

Kiedy piszesz

obj := *p 

kopiujesz wartości struct wskazany przez p (* dereferencji p). Jest ona podobna do:

var obj me = *p 

Więc obj jest nowa zmienna typu me, inicjowany do wartości *p. To powoduje, że obj ma inny adres pamięci.

Należy pamiętać, że obj if of type me, natomiast p jest typu *me. Ale są to oddzielne wartości. Zmiana wartości pola obj nie wpłynie na wartość tego pola w p (chyba że struktura me ma typ odwołania w nim jako pole, tj. Wycinek, mapę lub kanały. Patrz here i here.). Jeśli chcesz, aby doprowadzić do tego efektu, należy użyć:

obj := p 
// equivalent to: var obj *me = p 

Teraz obj punkty do tego samego obiektu jako p. Nadal mają różne adresy same w sobie, ale przechowują w nich ten sam adres rzeczywistego obiektu me.

+0

Czy istnieje sposób, aby uzyskać ten sam wskaźnik dereferencji do p? jak w func main(), jeśli dodajemy strukturę jako plaster, zawsze będziemy musieli usunąć ją z wewnątrz samego dopełnienia, tj. res = append (res, * p). – ken

+0

Nie chodzi tylko o "tworzenie" nowej zmiennej, przypisanie do istniejącej zmiennej poprzez dereferencję kopiuje wartość, np. '* a = * b' nadal kopiuje kopie' * b' na '* a'. – JimB

+0

@jimB yap, czy istnieje sposób na uniknięcie powtarzania kopii? ponieważ w zasadzie operacja po prostu musi zajmować się tym samym p struct. – ken

6

Nie, "przydział" zawsze tworzy kopię w Go, w tym przypisanie do argumentów funkcji i metody. Oświadczenie obj := *p kopiuje wartość *p do obj.

Jeśli zmienisz instrukcję p.color = "purple" na (*p).color = "purple" otrzymasz te same wyniki, ponieważ samo dereferencja p nie utworzy kopii.

+0

w rzeczywistości, pochodząc z c tła, to mnie pomylić. Dzięki, obie odpowiedzi są poprawne i docierają do mnie mniej więcej w tym samym czasie, więc wybierz więcej szczegółów, ale postaraj się o to również za odpowiedź! – ken

+0

"Samo dereferencja nie tworzy kopii", co wyjaśniło moje zamieszanie, dziękuję – stackoverflower