Références de plage au lieu de valeurs

90

J'ai vu que cette plage renvoie la clé et la "copie" de la valeur. Existe-t-il un moyen pour cette plage de renvoyer l'adresse de l'article? Exemple

package main

import "fmt"

type MyType struct {
    field string
}

func main() {
    var array [10]MyType

    for _, e := range array {
        e.field = "foo"
    }

    for _, e := range array {
        fmt.Println(e.field)
        fmt.Println("--")
    }
}

http://play.golang.org/p/AFOGG9NGpx

Ici, le "champ" n'est pas modifié car range envoie la copie du champ, dois-je utiliser l'index ou y a-t-il un autre moyen de modifier la valeur?

Merci d'avoir lu.

Épitouille
la source
4
duplication possible des valeurs
James Henstridge
1
Pouvez-vous utiliser un tableau de pointeur de MyType?
nvcnvn
Oui, si vous utilisez un tableau de pointeurs vous pouvez modifier les résultats directement dans le tableau sans avoir à utiliser l'index, il y a un exemple ici play.golang.org/p/_Vx7ONLDJs
notzippy
rangefonctionne bien et il renvoie ce que vous avez mis dans la tranche. Ici, les valeurs de type MyStruct(qui est un type valeur) résident à l'intérieur de la tranche. Au lieu de cela, nous pourrions mettre des pointeurs de type *MyStructà l'intérieur de la tranche. Si vous en avez absolument besoin pour fonctionner tel quel, vous pouvez utiliser des index au lieu des valeurs renvoyées par range.
Kaveh Shahbazian

Réponses:

123

La réponse courte et directe: non, utilisez l'index du tableau au lieu de la valeur

Ainsi, le code ci-dessus devient:

package main

import "fmt"

type MyType struct {
    field string
}

func main() {
    var array [10]MyType

    for idx, _ := range array {
        array[idx].field = "foo"
    }

    for _, e := range array {
        fmt.Println(e.field)
        fmt.Println("--")
    }
}
MushinNoShin
la source
30
Et bien sûr, si vous accédez à plusieurs reprises que array[idx]vous pourriez plutôt choisir d'avoir e := &array[idx]au sommet de la boucle, puis utiliser e.field1, e.field2etc qui ressemble plus à l'OP aurait voulu (juste avec deux lignes au lieu d'un).
Dave C
16
Vous pouvez déposer le , _tout -for idx := range array
Sam Toliman
0

Cela a déjà été dit dans les commentaires, mais pour ceux qui recherchent des réponses tout de suite, voici comment obtenir le résultat attendu en utilisant une tranche de pointeurs et en apportant le moins de modifications au code d'origine.

package main

import "fmt"

type MyType struct {
    field string
}

func main() {
    // Slice of pointers instead of slice of type
    var array [10]*MyType

    // Initialize array manually
    for idx := range array {
        array[idx] = &MyType{}
    }

    for _, e := range array {
        e.field = "foo"
    }

    for _, e := range array {
        fmt.Println(e.field)
        fmt.Println("--")
    }

}

Le voici en terrain de jeu

Jairo Lozano
la source
2
Le fait est que ce pointeur n'est utile que pour cette utilisation de plage. Je préférerais ajouter à l' e := &array[idx]intérieur de chaque plage qui ont ce pointeur vers un pointeur ...
Cirelli94
-1
package main

import "fmt"

type MyType struct {
    field string
}

func main() {
    var array [10]MyType

    for index := range array {
        array[index].field = "foo"
    }

    for _, e := range array {
        fmt.Println(e.field)
        fmt.Println("--")
    }
}
jukay
la source
Cela ne semble rien ajouter à la réponse acceptée existante (publiée il y a 6 ans).
Brits