Odniesienia do zakresów zamiast wartości

90

Widziałem, że zakres zwraca klucz i „kopię” wartości. Czy istnieje sposób, aby ten zakres zwrócił adres przedmiotu? Przykład

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

Tutaj "pole" nie jest modyfikowane, ponieważ zakres wysyła kopię pola, czy muszę używać indeksu, czy jest inny sposób na modyfikację wartości?

Dziękuje za przeczytanie.

Epitouille
źródło
4
możliwy duplikat wartości Change podczas iteracji w golang
James Henstridge,
1
Czy możesz użyć tablicy wskaźników MyType?
nvcnvn
Tak, jeśli używasz tablicy wskaźników, możesz modyfikować wyniki bezpośrednio w tablicy bez konieczności używania indeksu, jest tutaj przykład play.golang.org/p/_Vx7ONLDJs
notzippy
rangedziała dobrze i zwraca to, co umieściłeś w plasterku. Tutaj wartości typu MyStruct(który jest typem wartości) znajdują się wewnątrz plasterka. Zamiast tego moglibyśmy umieścić wskaźniki typu *MyStructwewnątrz wycinka. Jeśli absolutnie potrzebujesz, aby działał tak, jak jest, możesz użyć indeksów zamiast wartości zwracanych przez range.
Kaveh Shahbazian

Odpowiedzi:

123

Krótka i bezpośrednia odpowiedź: nie, użyj indeksu tablicy zamiast wartości

Tak więc powyższy kod staje się:

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
źródło
30
I oczywiście, jeśli wielokrotnie dostęp array[idx]można zamiast zdecydować się e := &array[idx]na szczycie pętli for a następnie użyć e.field1, e.field2itp, które bardziej przypomina OP może chciał (tylko z dwóch linii zamiast jednego).
Dave C
16
Możesz , _całkowicie zrezygnować z -for idx := range array
Sam Toliman
0

Zostało to już powiedziane w komentarzach, ale dla tych, którzy szukają odpowiedzi od razu, oto jak można osiągnąć oczekiwany rezultat, używając kawałka wskaźników i wprowadzając najmniej zmian w oryginalnym kodzie.

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

}

Tutaj jest na placu zabaw

Jairo Lozano
źródło
2
Faktem jest, że wskaźnik jest przydatny tylko w tym zakresie. Wolałbym dodać e := &array[idx]wewnątrz każdego zakresu, który ma ten wskaźnik, do wskaźnika ...
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
źródło
Wydaje się, że nie dodaje to niczego do istniejącej zaakceptowanej odpowiedzi (opublikowanej 6 lat temu).
Brytyjczycy