J'ai un type struct avec un *int64
champ.
type SomeType struct {
SomeField *int64
}
À un moment donné dans mon code, je veux déclarer un littéral de ceci (disons, quand je sais que ladite valeur devrait être 0, ou pointer vers un 0, vous savez ce que je veux dire)
instance := SomeType{
SomeField: &0,
}
... sauf que cela ne fonctionne pas
./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
Alors j'essaye ça
instance := SomeType{
SomeField: &int64(0),
}
... mais cela ne fonctionne pas non plus
./main.go:xx: cannot take the address of int64(0)
Comment puis-je faire cela? La seule solution que je peux trouver est d'utiliser une variable d'espace réservé
var placeholder int64
placeholder = 0
instance := SomeType{
SomeField: &placeholder,
}
Remarque: la Edit: non, ce n'est pas le cas. Désolé pour ça.&0
syntaxe fonctionne bien quand c'est un * int au lieu d'un *int64
.
Éditer:
Apparemment, ma question était trop ambiguë. Je cherche un moyen de déclarer littéralement a *int64
. Cela pourrait être utilisé dans un constructeur, ou pour énoncer des valeurs de struct littérales, ou même comme arguments pour d'autres fonctions. Mais les fonctions d'assistance ou l'utilisation d'un type différent ne sont pas des solutions que je recherche.
var _ *int64 = pointer.Int64(64)
Réponses:
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 ).
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éroint64
et obtenir son adresse: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:
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 legox
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
:Et en l'utilisant:
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
Ou comme alternative (plus courte):
5) Avec slice littéral, indexation et prise d'adresse
Si vous voulez
*SomeField
être autre que0
, alors vous avez besoin de quelque chose d'adressable.Vous pouvez toujours faire ça, mais c'est moche:
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é:
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:
Et maintenant nous pouvons faire:
Notez que ceci
signifie ce qui suit:
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):
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:
la source
instance
objets différents pointeraient vers deuxint64
s différents . Mais cela semble répondre correctement à l'intention des PO&[]int64{2}[0]
je pense que, d'après la description des constantes sur blog.golang.org/constants, cela devrait fonctionner comme&0
.instance
objets différentsint64
pointaient vers le même et que l'un modifiait l'objet pointé, les deux changeraient. Et si maintenant vous utilisiez le même littéral pour créer un 3einstance
? La même adresse pointerait maintenant vers uneint64
valeur différente ... donc une adresse différente devrait être utilisée, mais alors pourquoi utiliser la même dans le cas des 2 premiers?Utilisez une fonction qui renvoie une adresse d'une variable int64 pour résoudre le problème.
la source