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)
}
de 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
, i
es una variable int
en la ubicación de memoria (&i
) 0xf800000040
con un valor inicial (i
) 42
.
En función main
, p
es un puntero a una variable int
en la ubicación de memoria (&p
) 0xf8000000f0
con un valor (p
= &i
) 0xf800000040
que apunta a un valor int
(*p
= i
) 42
.
En función main
, byval(p)
es una llamada de función que asigna el valor (p
= &i
) 0xf800000040
del argumento en la ubicación de memoria (&p
) 0xf8000000f0
al parámetro de función byval
q
en la ubicación de memoria (&q
) 0xf8000000d8
. En otras palabras, la memoria se asigna para el byval
parámetro q
y se le asigna el valor del main
byval
argumento p
; los valores de p
y q
son inicialmente los mismos, pero las variables p
y son distintas.
En función byval
, utilizando puntero q
(*int
), que es una copia de puntero p
(*int
), número entero *q
(i
) se ajusta a un nuevo valor int 4143
. Al final antes de regresar. el puntero q
se establece en nil
(valor cero), que no tiene efecto en p
ya que q
es una copia.
En función main
, p
es un puntero a una variable int
en la ubicación de memoria (&p
) 0xf8000000f0
con un valor (p
= &i
) 0xf800000040
que apunta a un nuevo valor int
(*p
= i
) 4143
.
En función main
, i
es una variable int
en la ubicación de memoria (&i
) 0xf800000040
con un valor final (i
) 4143
.
En el ejemplo, la función main
variables s
utilizado como un argumento a la llamada de función gotest
no es el mismo que el parámetro de la función gotest
s
. Tienen el mismo nombre, pero son variables diferentes con diferentes ámbitos y ubicaciones de memoria. El parámetro de función s
oculta el argumento de llamada de función s
. Es por eso que en mi ejemplo, nombré las variables de argumento y parámetro p
y q
respectivamente para enfatizar la diferencia.
En su ejemplo, (&s
) 0x4930d4
es la dirección de la posición de memoria para la variable s
en función main
que se utiliza como un argumento a la llamada a la función gotest(s, done)
y 0x4974d8
es la dirección de la posición de memoria para la función gotest
parámetro s
. Si configura el parámetro s = nil
al final de la función gotest
, no tiene efecto en la variable s
en main
; s
en main
y s
en gotest
son ubicaciones distintas de memoria. En términos de tipos, &s
es **Something
, s
es *Something
, y *s
es Something
. &s
es un puntero a (dirección de la ubicación de la memoria) s
, que es un puntero a (dirección de la ubicación de la memoria) una variable anónima de tipo Something
. En términos de valores, main.&s != gotest.&s
, main.s == gotest.s
, main.*s == gotest.*s
y main.s.number == gotest.s.number
.
Debe seguir los consejos de mkb y dejar de usar println(&s)
. Utilice el paquete fmt
, por ejemplo,
fmt.Printf("%v %p %v\n", &s, s, *s)
punteros tienen el mismo valor cuando apuntan a la misma posición de memoria; los punteros tienen diferentes valores cuando apuntan a diferentes ubicaciones de memoria.
En mi ejemplo, el más usado toma un puntero a 'Algo', así que supongo que se refiere al mismo objeto, y claramente lo es, ya que después de cambiar el valor dentro de la rutina, el objeto también tiene su valor cambiado en el principal función. El valor del puntero impreso es diferente. –
@JamesDean En su ejemplo, está imprimiendo el valor del puntero & s tipo ** Algo, que no es lo mismo que el valor del puntero s tipo * Algo. Revisé mi ejemplo para pasar un puntero por valor. – peterSO
@James Dean Imprimió la dirección del puntero (es decir, un puntero al puntero 's'), - los punteros se pasan por valor, la dirección de' s' no es lo mismo que 's'. Si su función más deseada fue 'println (s)' intead, imprimiría el valor del puntero. – nos