L'intervallo fa riferimento invece ai valori


91

Ho visto che l'intervallo restituisce la chiave e la "copia" del valore. C'è un modo per quell'intervallo di restituire l'indirizzo dell'articolo? Esempio

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

Qui "campo" non viene modificato perché range invia la copia del campo, devo usare indice o c'è un altro modo per modificare il valore?

Grazie per aver letto.



1
Puoi usare una matrice di puntatore di MyType?
nvcnvn

Sì, se usi un array di puntatori puoi modificare i risultati direttamente nell'array senza dover usare l'indice, c'è un esempio qui play.golang.org/p/_Vx7ONLDJs
notzippy

rangefunziona bene e restituisce ciò che hai inserito nella fetta. Qui i valori di tipo MyStruct(che è un tipo di valore) risiedono all'interno della fetta. Invece potremmo mettere puntatori di tipo *MyStructall'interno della slice. Se hai assolutamente bisogno che funzioni così com'è, puoi usare gli indici invece dei valori restituiti da range.
Kaveh Shahbazian

Risposte:


126

La risposta breve e diretta: no, usa l'indice dell'array invece del valore

Quindi il codice sopra diventa:

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
E, naturalmente, se si accede più volte array[idx]si potrebbe invece scegliere di avere e := &array[idx]nella parte superiore del ciclo for e quindi utilizzare e.field1, e.field2ecc che assomiglia più da vicino l'OP avrebbe voluto (solo con due linee invece di uno).
Dave C

18
Puoi abbandonare , _completamente -for idx := range array
Sam Toliman il

0

È già stato detto nei commenti, ma per chi cerca subito risposte, ecco come ottenere il risultato atteso utilizzando una fetta di puntatori e apportando il minimo cambiamento al codice originale.

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

}

Eccolo nel parco giochi


2
Il fatto è che quel puntatore è utile solo per questo utilizzo dell'intervallo. Preferirei aggiungere e := &array[idx]all'interno di ogni intervallo che ha quel puntatore a un puntatore ...
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("--")
    }
}

1
Questo non sembra aggiungere nulla alla risposta accettata esistente (pubblicata 6 anni fa).
Brits
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.