Los argumentos de la función Go se pasan por valor.
Primero, descartemos las partes irrelevantes de su ejemplo, para que podamos ver fácilmente que simplemente está pasando un argumento por valor. Por ejemplo,
package main
import "fmt"
func byval(q *int) {
fmt.Printf("3. byval -- q %T: &q=%p q=&i=%p *q=i=%v\n", q, &q, q, *q)
*q = 4143
fmt.Printf("4. byval -- q %T: &q=%p q=&i=%p *q=i=%v\n", q, &q, q, *q)
q = nil
}
func main() {
i := int(42)
fmt.Printf("1. main -- i %T: &i=%p i=%v\n", i, &i, i)
p := &i
fmt.Printf("2. main -- p %T: &p=%p p=&i=%p *p=i=%v\n", p, &p, p, *p)
byval(p)
fmt.Printf("5. main -- p %T: &p=%p p=&i=%p *p=i=%v\n", p, &p, p, *p)
fmt.Printf("6. main -- i %T: &i=%p i=%v\n", i, &i, i)
}
Salida:
1. main -- i int: &i=0xf840000040 i=42
2. main -- p *int: &p=0xf8400000f0 p=&i=0xf840000040 *p=i=42
3. byval -- q *int: &q=0xf8400000d8 q=&i=0xf840000040 *q=i=42
4. byval -- q *int: &q=0xf8400000d8 q=&i=0xf840000040 *q=i=4143
5. main -- p *int: &p=0xf8400000f0 p=&i=0xf840000040 *p=i=4143
6. main -- i int: &i=0xf840000040 i=4143
En función main, ies una intvariable en la ubicación de la memoria ( &i) 0xf800000040con un valor inicial ( i) 42.
En función main, pes un puntero a una intvariable en la ubicación de la memoria ( &p) 0xf8000000f0con un valor ( p= &i) 0xf800000040que apunta a un intvalor ( *p= i) 42.
En función main, byval(p)es una llamada de función que asigna el valor ( p= &i) 0xf800000040del argumento en la ubicación de la memoria ( &p) 0xf8000000f0al byvalparámetro de la función qen la ubicación de la memoria ( &q) 0xf8000000d8. En otras palabras, se asigna memoria para el byvalparámetro qy se le asigna el valor del main byvalargumento p; los valores de py qson inicialmente los mismos, pero las variables py qson distintas.
En función byval, usando pointer q( *int), que es una copia de pointer p( *int), integer *q( i) se establece en un nuevo valor int 4143. Al final antes de regresar. el puntero qse establece en nil(valor cero), lo que no tiene ningún efecto sobre pya que qes una copia.
En función main, pes un puntero a una intvariable en la ubicación de la memoria ( &p) 0xf8000000f0con un valor ( p= &i) 0xf800000040que apunta a un nuevo intvalor ( *p= i) 4143.
En función main, ies una intvariable en la ubicación de la memoria ( &i) 0xf800000040con un valor final ( i) 4143.
En su ejemplo, la mainvariable de función sutilizada como argumento para la gotestllamada a la función no es la misma que el gotestparámetro de la función s. Tienen el mismo nombre, pero son variables diferentes con diferentes ámbitos y ubicaciones de memoria. El parámetro de función soculta el argumento de llamada a la función s. Es por eso que en mi ejemplo, nombré las variables de argumento y parámetro py qrespectivamente para enfatizar la diferencia.
En su ejemplo, ( &s) 0x4930d4es la dirección de la ubicación de la memoria para la variable sen la función mainque se usa como argumento para la llamada a la función gotest(s, done), y 0x4974d8es la dirección de la ubicación de la memoria para el gotestparámetro de la función s. Si establece el parámetro s = nilal final de la función gotest, no tiene ningún efecto en la variable sen main; sen mainy sen gotestson ubicaciones de memoria distintas. En términos de tipos, &ses **Something, ses *Somethingy *ses Something. &ses un puntero a (dirección de ubicación de memoria) s, que es un puntero a (dirección de ubicación de memoria) una variable anónima de tipoSomething. En cuanto a los valores, main.&s != gotest.&s, main.s == gotest.s, main.*s == gotest.*s, y main.s.number == gotest.s.number.
Debe seguir el sabio consejo de mkb y dejar de usarlo println(&s). Utilice el fmtpaquete, por ejemplo,
fmt.Printf("%v %p %v\n", &s, s, *s)
Los punteros tienen el mismo valor cuando apuntan a la misma ubicación de memoria; Los punteros tienen valores diferentes cuando apuntan a diferentes ubicaciones de memoria.
spuntero), - los punteros se pasan por valor, la dirección desno es la misma ques. Si su función más obtenida lo hizoprintln( s ), imprimirá el valor del puntero.En Go, los argumentos se pasan por valor.
package main import "fmt" type SomeStruct struct { e int } // struct passed by value func v(v SomeStruct) { fmt.Printf("v: %p %v\n", &v, v) v.e = 2 fmt.Printf("v: %p %v\n", &v, v) } // pointer to struct passed by value func p(p *SomeStruct) { fmt.Printf("p: %p %v\n", p, *p) p.e = 2 fmt.Printf("p: %p %v\n", p, *p) } func main() { var s SomeStruct s.e = 1 fmt.Printf("s: %p %v\n", &s, s) v(s) fmt.Printf("s: %p %v\n", &s, s) p(&s) fmt.Printf("s: %p %v\n", &s, s) }Salida:
s: 0xf800000040 {1} v: 0xf8000000e0 {1} v: 0xf8000000e0 {2} s: 0xf800000040 {1} p: 0xf800000040 {1} p: 0xf800000040 {2} s: 0xf800000040 {2}fuente
type sometype struct { } a := sometype {} b := int(2) println("Ptr to a", &a) println("Ptr to b", &b)fuente
package main import ( "fmt" ) func main() { a := 42 fmt.Println(&a) }resulta en:
0x1040a124Según Wikipedia :
fuente
package main import "fmt" func zeroval(ival int) { ival = 0 } func zeroptr(iptr *int) { *iptr = 0 } func main() { i := 1 fmt.Println("initial:", i) zeroval(i) fmt.Println("zeroval:", i) //The &i syntax gives the memory address of i, i.e. a pointer to i. zeroptr(&i) fmt.Println("zeroptr:", i) //Pointers can be printed too. fmt.Println("pointer:", &i) }SALIDA:
$ go run pointers.go initial: 1 zeroval: 1 zeroptr: 0 pointer: 0x42131100fuente