float64 - golang pointers to structs
¿Cómo hago un literal*int64 en Go? (2)
Usar una función que devuelva una dirección de una variable int64 resolverá el problema.
En el siguiente código usamos una función f que acepta un entero y devuelve un valor de puntero que contiene la dirección del entero. Al usar este método, podemos resolver fácilmente el problema anterior.
type myStr struct {
url *int64
}
func main() {
f := func(s int64) *int64 {
return &s
}
myStr{
url: f(12345),
}
}
Tengo un tipo de estructura con un campo
*int64
.
type SomeType struct {
SomeField *int64
}
En algún momento de mi código, quiero declarar un literal de esto (por ejemplo, cuando sé que dicho valor debe ser 0, o apuntando a un 0, ya sabes lo que quiero decir)
instance := SomeType{
SomeField: &0,
}
... excepto que esto no funciona
./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
Entonces intento esto
instance := SomeType{
SomeField: &int64(0),
}
... pero esto tampoco funciona
./main.go:xx: cannot take the address of int64(0)
¿Cómo hago esto? La única solución que se me ocurre es usar una variable de marcador de posición
var placeholder int64
placeholder = 0
instance := SomeType{
SomeField: &placeholder,
}
Nota: la sintaxis
Editar: no, no lo hace.
Perdón por esto.
&0
funciona
bien
cuando es * int en lugar de
*int64
.
Editar:
Aparentemente había demasiada ambigüedad en mi pregunta.
Estoy buscando una manera de decir
literalmente
un
*int64
.
Esto podría usarse dentro de un constructor, o para establecer valores de estructura literales, o incluso como argumentos para otras funciones.
Pero las funciones de ayuda o el uso de un tipo diferente no son soluciones que estoy buscando.
La especificación de idioma de Go ( operadores de dirección ) no permite tomar la dirección de una constante numérica (no de una constante sin tipo ni de tipo ).
El operando debe ser direccionable , es decir, una operación de indexación indirecta, de puntero o variable; 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, vea la pregunta relacionada: Encuentre la dirección de la constante en marcha . Una pregunta similar (de manera similar, no se permite tomar su dirección): ¿Cómo puedo almacenar referencias al resultado de una operación en Go?
Tus opciones (prueba todo en Go Playground ):
1) Con
new()
Simplemente puede usar la función incorporada
new()
para asignar un nuevo
int64
valor
int64
y obtener su dirección:
instance := SomeType{
SomeField: new(int64),
}
Pero tenga en cuenta que esto solo se puede utilizar para asignar y obtener un puntero al valor cero de cualquier tipo.
2) Con variable auxiliar
Más simple y recomendado para elementos distintos de cero es usar una variable auxiliar cuya dirección se pueda tomar:
helper := int64(2)
instance2 := SomeType{
SomeField: &helper,
}
3) Con función auxiliar
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 un análisis de escape y asigna variables locales en el montón (en lugar de 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 línea
instance4 := SomeType{
SomeField: func() *int64 { i := int64(4); return &i }(),
}
O como una alternativa (más corta):
instance4 := SomeType{
SomeField: func(i int64) *int64 { return &i }(4),
}
5) Con corte literal, indexando y tomando dirección
Si desea que
*SomeField
sea distinto de
0
, entonces necesita 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 se crea un segmento
[]int64
con un literal, que tiene un elemento (
5
).
Y se indexa (elemento 0) y se toma la dirección del elemento 0.
En el fondo, también se asignará una matriz de
[1]int64
y se utilizará como matriz de respaldo para el segmento.
Así que hay muchas repeticiones aquí.
6) Con una estructura de ayuda literal
Examinemos la excepción a los requisitos de direccionamiento:
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 asignado el valor de estructura y se obtendrá un puntero.
Pero si es así, otro requisito estará disponible para nosotros:
"selector de campo de un operando de estructura direccionable"
.
Entonces, si el literal de estructura contiene un campo de tipo
int64
, ¡también podemos tomar la dirección de ese campo!
Veamos esta opción en acción. Utilizaremos 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" como operador de dirección
&
se aplica al resultado de la
expresión del selector
.
También tenga en cuenta que en el fondo sucederá lo siguiente (esta también es una sintaxis válida):
&(*(&intwrapper{6})).x
7) Con ayudante anónimo struct literal
El principio es el mismo que para el caso # 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 / envoltorio:
instance7 := SomeType{
SomeField: &(&struct{ x int64 }{7}).x,
}