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.


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("--")
    }
}

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


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("--")
    }
}

Cela ne semble rien ajouter à la réponse acceptée existante (publiée il y a 6 ans).
Brits
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.