web-dev-qa-db-fra.com

Comment faire un * int64 littéral dans Go?

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 ce (par exemple, quand je sais que ladite valeur doit être 0, ou en pointant sur 0, vous voyez 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

Alors 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 peux trouver est d'utiliser une variable d'espace réservé

var placeholder int64
placeholder = 0

instance := SomeType{
    SomeField: &placeholder,
}

Noter la &0 La syntaxe fonctionne très bien quand il s’agit d’un * int au lieu d’un *int64. Edit: non ce n'est pas le cas. Désolé pour ça.

Modifier:

Apparemment, il y avait trop d'ambiguïté dans ma question. Je cherche un moyen de littéralement a *int64. Cela pourrait être utilisé dans un constructeur, ou pour énoncer des valeurs de structure littérales, ou même comme arguments à d'autres fonctions. Mais les fonctions d'assistance ou l'utilisation d'un type différent ne sont pas des solutions que je recherche.

75
ThisGuy

La spécification de langue Go ( opérateurs d'adresse ) ne permet pas de prendre l'adresse d'une constante numérique (pas d'un non typé ni d'un typé constante).

L'opérande doit être adressable, c'est-à-dire une opération de variable, d'indirection de pointeur ou d'indexation 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 (éventuellement entre parenthèses) littéral composite .

Pour savoir pourquoi ceci n'est pas autorisé, voir la question connexe: Trouver l'adresse de la constante dans go . Une question similaire (non autorisée à prendre son adresse): Comment puis-je stocker une référence au résultat d'une opération dans Go?

Vos options (essayez tout sur le Go Playground ):

1) Avec new()

Vous pouvez simplement utiliser la fonction intégrée new() pour allouer un nouveau 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 n'importe quel 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

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),
}

Notez que nous n’avons réellement alloué aucune ressource, 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 risquent d'échapper à la fonction. Pour plus de détails, voir Est-ce que le retour d'une tranche d'un tableau local dans une fonction Go est sans danger?

4) avec une fonction anonyme one-liner

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 que *SomeField Soit différent de 0, Vous avez besoin de quelque chose d'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 est une tranche []int64 Est créée avec un littéral, ayant 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.

6) Avec un assistant littéral

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 (éventuellement entre parenthèses) littéral composite .

Cela signifie que prendre l'adresse d'un littéral composite, par ex. un littéral struct est ok. Si nous le faisons, nous aurons la valeur de structure allouée et un pointeur obtenu. Mais si tel est le cas, une autre exigence nous sera disponible: "sélecteur de champ d'un opérande struct adressable" . Donc, si le littéral struct contient un champ de type int64, Nous pouvons 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 on peut faire:

instance6 := SomeType{
    SomeField: &(&intwrapper{6}).x,
}

Notez que cela

&(&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 expression de sélecteur .

Notez également qu'en arrière-plan, les événements suivants se produiront (il s'agit également d'une syntaxe valide):

&(*(&intwrapper{6})).x

7) Avec helper anonymous struct literal

Le principe est le même que dans le cas n ° 6, mais nous pouvons également utiliser un littéral struct anonyme, aussi aucune définition de type struct helper/wrapper n'est nécessaire:

instance7 := SomeType{
    SomeField: &(&struct{ x int64 }{7}).x,
}
161
icza

Utilisez une fonction qui renvoie l'adresse d'une variable int64 pour résoudre le problème.

Dans le code ci-dessous, nous utilisons une fonction f qui accepte un entier et renvoie une valeur de pointeur contenant l'adresse du entier. En utilisant cette méthode, nous pouvons facilement résoudre le problème ci-dessus.

 type myStr struct {
        url *int64
    }

    func main() {

        f := func(s int64) *int64 {
            return &s
        }
        myStr{
            url: f(12345),
        }
    }
3
ASHWIN RAJEEV