¿Cómo puedo almacenar la referencia al resultado de una operación en Go?

De acuerdo, es difícil describirlo en palabras, pero digamos que tengo un mapa que almacena punteros int , y quiero almacenar el resultado de una operación como otra clave en mi hash:

 m := make(map[string]*int) m["d"] = &(*m["x"] + *m["y"]) 

Esto no funciona y me da el error: cannot take the address of *m["x"] & *m["y"]

¿Pensamientos?

Un puntero es una dirección de memoria. Por ejemplo, una variable tiene una dirección en la memoria.

El resultado de una operación como 3 + 4 no tiene una dirección porque no hay memoria específica asignada para ella. El resultado puede simplemente vivir en registros de procesador.

Debe asignar memoria cuya dirección puede colocar en el mapa. Lo más fácil y directo es crear una variable local para él.

Mira este ejemplo:

 x, y := 1, 2 m := map[string]*int{"x": &x, "y": &y} d := *m["x"] + *m["y"] m["d"] = &d fmt.Println(m["d"], *m["d"]) 

Salida (pruébalo en el área de juegos Go ):

 0x10438300 3 

Nota: Si el código anterior está en una función, la dirección de la variable local ( d ) que acabamos de poner en el mapa continuará en vigencia incluso si regresamos de la función (es decir, si el map se devuelve o se crea fuera) por ejemplo, una variable global). En Go, es perfectamente seguro tomar y devolver la dirección de una variable local. El comstackdor analizará el código y si la dirección (puntero) escapa de la función, se asignará automáticamente en el montón (y no en la stack). Para más detalles, consulte las preguntas frecuentes: ¿Cómo puedo saber si una variable está asignada en el montón o la stack?

Nota n. ° 2: hay otras maneras de crear un puntero a un valor (como se detalla en esta respuesta: ¿Cómo hago un literal * int64 en Go? ), Pero son solo “trucos” y no son más agradables ni más eficientes. Usar una variable local es la manera más limpia y recomendada.

Por ejemplo, esto también funciona sin crear una variable local, pero obviamente no es intuitiva en absoluto:

 m["d"] = &[]int{*m["x"] + *m["y"]}[0] 

La salida es igual. Pruébalo en el patio de juegos Go .

El resultado de la adición se coloca en algún lugar transitorio (en la stack) y, por lo tanto, no sería seguro tomar su dirección. Debería poder solucionar esto asignando explícitamente un int en el montón para contener su resultado:

 result := make(int) *result = *m["x"] + *m["y"] m["d"] = result 

En Go, no puede tomar la referencia de un valor literal (formalmente conocido como un valor r). Pruebe lo siguiente:

 package main import "fmt" func main() { x := 3; y := 2; m := make(map[string]*int) m["x"] = &x m["y"] = &y f := *m["x"] + *m["y"] m["d"] = &f fmt.Printf("Result: %d\n",*m["d"]) } 

Eche un vistazo a este tutorial.