2015-12-30 7 views
6

Dire che voglio passare un puntatore a una funzione e modificare il valore di una struttura a cui punta il puntatore. Io normalmente fare questo dereferenziazione il puntatore:Ottenere valori diversi passando i puntatori a una funzione in Go

type Test struct { Value int} 
func main() { 
    var i Test = Test {2} 
    var p *Test = &i 
    f(p) 
    println(i.Value) // 4 
} 
func f(p *Test) { 
    *p = Test{4} 
} 

La mia domanda è: perché questo codice non cambia il valore

type Test struct { Value int} 
func main() { 
    var i Test = Test {2} 
    var p *Test = &i 
    f(p) 
    println(i.Value) // 2 
} 
func f(p *Test) { 
    // ? 
    p = &Test{4} 
} 

mentre questo si fa:

type Test struct { Value int} 
func main() { 
    var i Test = Test {2} 
    var p *Test = &i 
    f(p) 
    println(i.Value) // 4 
} 
func f(p *Test) { 
    p.Value = 4 
} 

risposta

13

Perché questa riga:

p = &Test{4} 

Assegna semplicemente un nuovo valore di puntatore alla variabile p. All'interno della funzione f(), p è solo una variabile locale. Assegnando un nuovo valore a p, si modifica semplicemente il valore della variabile locale e non il valore puntato.

La variabile locale p in f() non ha nulla a che fare con la variabile locale p in main(). Se si modifica p in f(), non cambierà p in main() (e non cambierà nemmeno il valore della struttura puntata).

Nel secondo esempio:

p.Value = 4 

Si tratta di una scorciatoia per:

(*p).Value = 4 

Questo cambia la rilevare valore, da cui si potrà osservare il cambiamento quando f() ritorni.

Nota:

Proprio come una nota a margine, se nella funzione main() si dovrebbe passare l'indirizzo del p (la variabile locale in main() che è un puntatore) di funzionare f(), è possibile modificare l'indirizzo memorizzato in di principale p:

func f(p **Test) { 
    *p = &Test{4} 
} 

E da main(), chiamare le cose come:

var i Test = Test{2} 
var p *Test = &i 
f(&p) 
println(i.Value) // 2 - Note that 'i' won't change! 
println(p.Value) // 4 - Only the address in 'p' to the new struct value created in f() 

Ma ovviamente passare un singolo puntatore *Test e modificare il valore puntato (p.Value = 4) è più efficiente, molto più comodo e molto più pulito.