J’ai un type de structure avec un champ *int64
.
type SomeType struct { SomeField *int64 }
À un moment donné dans mon code, je veux déclarer un littéral de ceci (par exemple, quand je sais que cette valeur doit être 0 ou un 0, vous savez ce que je veux dire)
instance := SomeType{ SomeField: &0, }
… sauf que ça ne marche pas
./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
Donc j’essaye ça
instance := SomeType{ SomeField: &int64(0), }
… mais ça ne marche pas non plus
./main.go:xx: cannot take the address of int64(0)
Comment puis-je faire cela? La seule solution que je puisse trouver consiste à utiliser une variable d’espace réservé
var placeholder int64 placeholder = 0 instance := SomeType{ SomeField: &placeholder, }
Note: la syntaxe Edit: non, ce n’est pas le cas. Désolé pour ça. &0
fonctionne bien quand c’est un * int au lieu d’un *int64
.
Modifier:
Par ailleurs, il y avait trop d’ambiguïté dans ma question. Je cherche un moyen d’ affirmer littéralement un *int64
. Cela pourrait être utilisé à l’intérieur d’un constructeur, ou pour définir des valeurs de structure littérales, ou même comme arguments pour d’autres fonctions. Mais les fonctions d’aide ou l’utilisation d’un type différent ne sont pas des solutions que je recherche.
La spécification de langue de destination ( 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 soit une variable, une indirection de pointeur, soit une opération d’indexation de tranche; ou un sélecteur de champ d’un opérande struct structuré; 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 raisonner pourquoi cela n’est pas autorisé, voir la question connexe: Rechercher l’adresse de constante dans go . Une question similaire (de même non autorisé à prendre son adresse): Comment puis-je stocker la référence au résultat d’une opération dans Go?
Vos options (essayez tous sur le terrain de jeu Go ):
new()
Vous pouvez simplement utiliser la fonction new()
intégrée pour allouer un nouvel int64
valeur zéro et obtenir son adresse:
instance := SomeType{ SomeField: new(int64), }
Mais notez que cela ne peut être utilisé que pour allouer et obtenir un pointeur sur la valeur zéro de tout type.
Le plus simple et recommandé pour les éléments non nuls est d’utiliser une variable auxiliaire dont l’adresse peut être prise:
helper := int64(2) instance2 := SomeType{ SomeField: &helper, }
Ou si vous en avez besoin plusieurs fois, vous pouvez créer une fonction d’assistance qui alloue et retourne un *int64
:
func create(x int64) *int64 { return &x }
Et en l’utilisant:
instance3 := SomeType{ SomeField: create(3), }
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), }
Si vous voulez que *SomeField
soit différent de 0
, alors vous avez besoin de quelque chose adressable.
Vous pouvez toujours le faire, 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 tranche []int64
est créée avec un littéral, avec un élément ( 5
). Et il est indexé (0ème élément) et l’adresse du 0ème é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. Donc, il y a beaucoup de passe-partout ici.
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 acceptable. Si nous le faisons, la structure sera affectée et un pointeur sera obtenu. Mais si tel est le cas, une autre exigence deviendra disponible pour nous: “sélecteur de champ d’un struct operand adressable” . Donc si le struct literal contient un champ de type int64
, on peut aussi prendre l’adresse de ce champ!
Voyons cette option en action. Nous allons utiliser 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” comme opérateur d’adresse &
est appliquée au résultat de l’ expression du sélecteur .
Notez également que ce qui suit se produira (ceci est également une syntaxe valide):
&(*(&intwrapper{6})).x
Le principe est le même que dans le cas n ° 6, mais nous pouvons également utiliser un littéral struct anonyme, de sorte qu’aucune définition de type de structure assistant / wrapper n’est nécessaire:
instance7 := SomeType{ SomeField: &(&struct{ x int64 }{7}).x, }