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.



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

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


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

Wydaje się, że nie dodaje to niczego do istniejącej zaakceptowanej odpowiedzi (opublikowanej 6 lat temu).
Brytyjczycy
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.