La especificación del lenguaje Go ( operadores de direcciones ) no permite tomar la dirección de una constante numérica (no de un sin tipo ni de un escrito constante).
El operando debe ser direccionable , es decir, una variable, una dirección indirecta del puntero o una operación de indexación de sectores; o un selector de campo de un operando de estructura direccionable; o una operación de indexación de matriz de una matriz direccionable. Como excepción al requisito de direccionabilidad, x
[en la expresión de &x
] también puede ser un literal compuesto (posiblemente entre paréntesis) .
Para razonar por qué esto no está permitido, consulte la pregunta relacionada: Buscar la dirección de la constante en marcha . Una pregunta similar (tampoco se permite tomar su dirección): ¿Cómo puedo almacenar una referencia al resultado de una operación en Go?
Tus opciones (prueba todas en Go Playground ):
1) Con new()
Simplemente puede usar la new()
función incorporada para asignar un nuevo valor cero int64
y obtener su dirección:
instance := SomeType{
SomeField: new(int64),
}
Pero tenga en cuenta que esto solo se puede usar para asignar y obtener un puntero al valor cero de cualquier tipo.
2) Con variable auxiliar
Lo más simple y recomendado para elementos distintos de cero es utilizar una variable auxiliar cuya dirección se pueda tomar:
helper := int64(2)
instance2 := SomeType{
SomeField: &helper,
}
3) Con función auxiliar
Nota: Las funciones auxiliares para adquirir un puntero a un valor distinto de cero están disponibles en mi github.com/icza/gox
biblioteca, en el gox
paquete, por lo que no tiene que agregarlas a todos sus proyectos donde las necesite.
O si lo necesita muchas veces, puede crear una función auxiliar que asigne y devuelva un *int64
:
func create(x int64) *int64 {
return &x
}
Y usándolo:
instance3 := SomeType{
SomeField: create(3),
}
Tenga en cuenta que en realidad no asignamos nada, el compilador Go lo hizo cuando devolvimos la dirección del argumento de la función. El compilador Go realiza análisis de escape y asigna variables locales en el montón (en lugar de en la pila) si pueden escapar de la función. Para obtener más información, consulte ¿Es seguro devolver una porción de una matriz local en una función Go?
4) Con una función anónima de una sola línea
instance4 := SomeType{
SomeField: func() *int64 { i := int64(4); return &i }(),
}
O como alternativa (más corta):
instance4 := SomeType{
SomeField: func(i int64) *int64 { return &i }(4),
}
5) Con literal de corte, indexación y toma de dirección
Si quieres *SomeField
ser diferente a 0
, entonces necesitas algo direccionable.
Todavía puedes hacer eso, pero eso es feo:
instance5 := SomeType{
SomeField: &[]int64{5}[0],
}
fmt.Println(*instance2.SomeField) // Prints 5
Lo que sucede aquí es que []int64
se crea un segmento con un literal, que tiene un elemento ( 5
). Y se indexa (elemento 0) y se toma la dirección del elemento 0. En segundo plano [1]int64
, también se asignará una matriz de y se utilizará como matriz de respaldo para el segmento. Así que hay mucho texto estándar aquí.
6) Con una estructura de ayuda literal
Examinemos la excepción a los requisitos de direccionabilidad:
Como excepción al requisito de direccionabilidad, x
[en la expresión de &x
] también puede ser un literal compuesto (posiblemente entre paréntesis) .
Esto significa que tomar la dirección de un literal compuesto, por ejemplo, un literal de estructura está bien. Si lo hacemos, tendremos el valor de la estructura asignado y un puntero obtenido. Pero si es así, otro requisito estará disponible para nosotros: "selector de campo de un operando de estructura direccionable" . Entonces, si la estructura literal contiene un campo de tipo int64
, ¡también podemos tomar la dirección de ese campo!
Veamos esta opción en acción. Usaremos este tipo de estructura de envoltura:
type intwrapper struct {
x int64
}
Y ahora podemos hacer:
instance6 := SomeType{
SomeField: &(&intwrapper{6}).x,
}
Tenga en cuenta que esto
&(&intwrapper{6}).x
significa lo siguiente:
& ( (&intwrapper{6}).x )
Pero podemos omitir el paréntesis "externo" ya que el operador de dirección &
se aplica al resultado de la expresión del selector .
También tenga en cuenta que en segundo plano sucederá lo siguiente (esta también es una sintaxis válida):
&(*(&intwrapper{6})).x
7) Con ayuda de estructura anónima literal
El principio es el mismo que con el caso n. ° 6, pero también podemos usar un literal de estructura anónimo, por lo que no se necesita una definición de tipo de estructura auxiliar / contenedor:
instance7 := SomeType{
SomeField: &(&struct{ x int64 }{7}).x,
}