Rentang referensi bukan nilai

90

Saya melihat rentang itu mengembalikan kunci dan "salinan" nilainya. Apakah ada cara untuk rentang tersebut untuk mengembalikan alamat item? Contoh

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

Di sini "bidang" tidak diubah karena rentang mengirimkan salinan bidang, Apakah saya harus menggunakan indeks atau adakah cara lain untuk mengubah nilai?

Terima kasih sudah membaca.

Epitouille
sumber
4
kemungkinan duplikat nilai Perubahan saat iterasi di golang
James Henstridge
1
Bisakah Anda menggunakan array penunjuk MyType?
nvcnvn
Ya, jika Anda menggunakan array pointer Anda dapat mengubah hasil langsung dalam array tanpa harus menggunakan indeks, ada contoh di sini play.golang.org/p/_Vx7ONLDJs
notzippy
rangeberfungsi dengan baik & mengembalikan apa yang telah Anda masukkan ke dalam potongan. Berikut nilai-nilai tipe MyStruct(yang merupakan tipe nilai) berada di dalam irisan. Sebagai gantinya kita bisa meletakkan pointer tipe *MyStructdi dalam slice. Jika Anda benar-benar membutuhkannya agar berfungsi sebagaimana mestinya, Anda dapat menggunakan indeks sebagai ganti nilai yang dikembalikan oleh range.
Kaveh Shahbazian

Jawaban:

123

Jawaban singkat & langsung: tidak, gunakan indeks array sebagai ganti nilainya

Jadi kode diatas menjadi:

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
sumber
30
Dan tentu saja, jika Anda berulang kali mengakses array[idx]Anda bisa malah memilih untuk memiliki e := &array[idx]di bagian atas untuk loop dan kemudian menggunakan e.field1, e.field2, dll yang lebih mirip OP mungkin ingin (hanya dengan dua baris bukan satu).
Dave C
16
Anda dapat menghentikan , _seluruhnya -for idx := range array
Sam Toliman
0

Sudah dikatakan di komentar, tetapi bagi mereka yang mencari jawaban segera, berikut ini cara Anda dapat mencapai hasil yang diharapkan dengan menggunakan sepotong petunjuk dan dengan membuat sedikit perubahan pada kode asli.

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

}

Ini dia di taman bermain

Jairo Lozano
sumber
2
Faktanya adalah, pointer itu hanya berguna untuk penggunaan rentang ini. Saya lebih suka menambahkan e := &array[idx]di dalam setiap rentang yang memiliki penunjuk itu ke penunjuk ...
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
sumber
Ini sepertinya tidak menambahkan apa pun ke jawaban yang diterima yang ada (diposting 6 tahun yang lalu).
Brits