Bereichsreferenzen statt Werte

90

Ich habe gesehen, dass der Bereich den Schlüssel und die "Kopie" des Werts zurückgibt. Gibt es eine Möglichkeit für diesen Bereich, die Adresse des Artikels zurückzugeben? Beispiel

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

Hier wird "Feld" nicht geändert, da der Bereich die Kopie des Felds sendet. Muss ich einen Index verwenden oder gibt es eine andere Möglichkeit, den Wert zu ändern?

Danke fürs Lesen.

Epitouille
quelle
4
Mögliches Duplikat der Änderungswerte während der Iteration in Golang
James Henstridge
1
Können Sie ein Array von Zeigern von verwenden MyType?
nvcnvn
Ja, wenn Sie ein Array von Zeigern verwenden, können Sie die Ergebnisse direkt im Array ändern, ohne den Index verwenden zu müssen. Hier finden Sie ein Beispiel. Play.golang.org/p/_Vx7ONLDJs
notzippy
rangefunktioniert einwandfrei und gibt zurück, was Sie in das Slice eingefügt haben. Hier befinden sich Werte vom Typ MyStruct(bei denen es sich um einen Werttyp handelt) innerhalb des Slice. Stattdessen könnten wir Zeiger vom Typ *MyStructin das Slice einfügen. Wenn Sie es unbedingt benötigen, um so zu funktionieren, wie es ist, können Sie Indizes anstelle der von zurückgegebenen Werte verwenden range.
Kaveh Shahbazian

Antworten:

122

Die kurze und direkte Antwort: Nein, verwenden Sie den Array-Index anstelle des Werts

So wird der obige Code:

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
quelle
30
Und natürlich, wenn Sie immer wieder zugreifen array[idx]könnten Sie stattdessen wählen haben e := &array[idx]an der Spitze der for - Schleife und dann verwenden e.field1, e.field2usw. , die näher der OP ähneln vielleicht gewünscht hat (nur mit zwei Linien statt eins).
Dave C
16
Sie können die , _vollständig fallen lassen -for idx := range array
Sam Toliman
0

Es wurde bereits in den Kommentaren gesagt, aber für diejenigen, die sofort nach Antworten suchen, ist hier, wie Sie das erwartete Ergebnis erzielen können, indem Sie ein Stück Zeiger verwenden und die geringsten Änderungen am Originalcode vornehmen.

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

}

Hier ist es auf dem Spielplatz

Jairo Lozano
quelle
2
Tatsache ist, dass der Zeiger nur für diesen Bereich nützlich ist. Ich würde es vorziehen, e := &array[idx]in jedem Bereich, der diesen Zeiger hat, einen Zeiger
hinzuzufügen
-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
quelle
Dies scheint der bestehenden akzeptierten Antwort (veröffentlicht vor 6 Jahren) nichts hinzuzufügen.
Briten