2016-07-18 152 views
5

Perché quando facciamo riferimento a struct usando (* structObj), golang sembra restituire una nuova copia di structObj che restituisca lo stesso indirizzo di structObj originale? Potrebbe essere un po 'fraintendere mio su questo, quindi cercare tipo chiarimentiis 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) 
} 

uscita

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

risposta

2

Quando si scrive

obj := *p 

si sta copiando il valore di struct indicato da p (* dereferenze p). E 'simile a:

var obj me = *p 

Così obj è una nuova variabile di tipo me, essendo inizializzato al valore della *p. Ciò causa che obj ha un diverso indirizzo di memoria.

Si noti che obj se di tipo me, mentre p è di tipo *me. Ma sono valori separati. La modifica di un valore di un campo di obj non influirà sul valore di tale campo in p (a meno che la struttura me non abbia un tipo di riferimento come campo, cioè fetta, mappa o canali.) Vedere here e here.). Se si vuole realizzare in tal senso, utilizzare:

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

ora obj punti per lo stesso oggetto come p. Hanno ancora indirizzi diversi, ma conservano al loro interno lo stesso indirizzo dell'oggetto reale me.

+0

c'è un modo per ottenere lo stesso puntatore dereferenziato a p? come nella funzione main(), se stiamo aggiungendo la struct come slice, dovremo sempre dereferenziarla all'interno dell'append, cioè res = append (res, * p). – ken

+0

Non si tratta solo di "creare" una nuova variabile, l'assegnazione ad una variabile esistente tramite una dereferenziatura copia il valore, ad es. '* a = * b' copia ancora copia' * b' a '* a'. – JimB

+0

@jimB yap, c'è un modo per evitare la copia ripetuta? in pratica l'operazione ha solo bisogno di occuparsi della stessa struttura. – ken

6

No, "assegnazione" crea sempre una copia in Go, inclusa l'assegnazione agli argomenti della funzione e del metodo. La dichiarazione obj := *p copia il valore di *p a obj.

Se si modifica la dichiarazione p.color = "purple" a (*p).color = "purple" si otterrà lo stesso risultato, poiché il dereferenziazione p non crea una copia.

+0

infatti, provenendo da c background, questo mi confonde. Grazie, pensate che entrambe le risposte sono corrette e raggiungetemi all'incirca nello stesso tempo, quindi scegliete un altro dettaglio, ma invertire questo anche per la vostra risposta! – ken

+0

'dereferencing p stesso non crea una copia' questo ha chiarito la mia confusione, grazie – stackoverflower