La spécification du langage Go ( opérateurs d'adresse ) ne permet pas de prendre l'adresse d'une constante numérique (pas d'une constante non typée ni d'une constante typée ).
L'opérande doit être adressable , c'est-à-dire une opération d'indexation de variable, d'indirection de pointeur ou de tranche; ou un sélecteur de champ d'un opérande struct adressable; ou une opération d'indexation de tableau d'un tableau adressable. En tant qu'exception à l'exigence d'adressabilité, x
[dans l'expression de &x
] peut également être un littéral composite (éventuellement entre parenthèses) .
Pour savoir pourquoi cela n'est pas autorisé, consultez la question associée: Rechercher l'adresse de la constante dans go . Une question similaire (de même pas autorisé à prendre son adresse): Comment puis-je stocker une référence au résultat d'une opération dans Go?
Vos options (tout essayer sur le Go Playground ):
1) Avec new()
Vous pouvez simplement utiliser la new()
fonction intégrée pour allouer une nouvelle valeur zéro int64
et obtenir son adresse:
instance := SomeType{
SomeField: new(int64),
}
Mais notez que cela ne peut être utilisé que pour allouer et obtenir un pointeur vers la valeur zéro de tout type.
2) Avec variable d'assistance
Le plus simple et recommandé pour les éléments non nuls est d'utiliser une variable d'assistance dont l'adresse peut être prise:
helper := int64(2)
instance2 := SomeType{
SomeField: &helper,
}
3) avec fonction d'assistance
Remarque: les fonctions d'assistance pour acquérir un pointeur vers une valeur non nulle sont disponibles dans ma github.com/icza/gox
bibliothèque, dans le gox
package, vous n'avez donc pas à les ajouter à tous vos projets là où vous en avez besoin.
Ou si vous en avez besoin plusieurs fois, vous pouvez créer une fonction d'assistance qui alloue et renvoie un *int64
:
func create(x int64) *int64 {
return &x
}
Et en l'utilisant:
instance3 := SomeType{
SomeField: create(3),
}
Notez qu'en fait nous n'avons rien alloué, le compilateur Go l'a fait lorsque nous avons renvoyé l'adresse de l'argument de la fonction. Le compilateur Go effectue une analyse d'échappement et alloue des variables locales sur le tas (au lieu de la pile) si elles peuvent échapper à la fonction. Pour plus de détails, voir Le retour d'une tranche d'un tableau local dans une fonction Go est-il sûr?
4) Avec une fonction anonyme sur une seule ligne
instance4 := SomeType{
SomeField: func() *int64 { i := int64(4); return &i }(),
}
Ou comme alternative (plus courte):
instance4 := SomeType{
SomeField: func(i int64) *int64 { return &i }(4),
}
5) Avec slice littéral, indexation et prise d'adresse
Si vous voulez *SomeField
être autre que 0
, alors vous avez besoin de quelque chose d'adressable.
Vous pouvez toujours faire ça, mais c'est moche:
instance5 := SomeType{
SomeField: &[]int64{5}[0],
}
fmt.Println(*instance2.SomeField) // Prints 5
Ce qui se passe ici, c'est qu'une []int64
tranche est créée avec un littéral, ayant un élément ( 5
). Et il est indexé (0e élément) et l'adresse du 0e élément est prise. En arrière-plan, un tableau de [1]int64
sera également alloué et utilisé comme tableau de sauvegarde pour la tranche. Il y a donc beaucoup de passe-partout ici.
6) Avec une structure d'aide littérale
Examinons l'exception aux exigences d'adressabilité:
En tant qu'exception à l'exigence d'adressabilité, x
[dans l'expression de &x
] peut également être un littéral composite (éventuellement entre parenthèses) .
Cela signifie que prendre l'adresse d'un littéral composite, par exemple un littéral struct est ok. Si nous le faisons, nous aurons la valeur struct allouée et un pointeur obtenu vers elle. Mais si c'est le cas, une autre exigence deviendra disponible pour nous: "sélecteur de champ d'un opérande struct adressable" . Donc, si le littéral struct contient un champ de type int64
, on peut également prendre l'adresse de ce champ!
Voyons cette option en action. Nous utiliserons ce type de structure wrapper:
type intwrapper struct {
x int64
}
Et maintenant nous pouvons faire:
instance6 := SomeType{
SomeField: &(&intwrapper{6}).x,
}
Notez que ceci
&(&intwrapper{6}).x
signifie ce qui suit:
& ( (&intwrapper{6}).x )
Mais nous pouvons omettre la parenthèse "externe" car l'opérateur d'adresse &
est appliqué au résultat de l' expression de sélecteur .
Notez également qu'en arrière-plan, ce qui suit se produira (c'est également une syntaxe valide):
&(*(&intwrapper{6})).x
7) Avec helper anonyme struct literal
Le principe est le même que dans le cas n ° 6, mais nous pouvons également utiliser un littéral struct anonyme, donc aucune définition de type struct helper / wrapper n'est nécessaire:
instance7 := SomeType{
SomeField: &(&struct{ x int64 }{7}).x,
}