Натомість значення посилання на діапазон


90

Я бачив, що діапазон повертає ключ і "копію" значення. Чи є спосіб для цього діапазону повернути адресу товару? Приклад

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

Тут "поле" не модифікується, оскільки діапазон надсилає копію поля. Чи потрібно мені використовувати індекс або є інший спосіб змінити значення?

Дякуємо за читання.



1
Чи можете ви використовувати масив вказівника на MyType?
nvcnvn

Так, якщо ви використовуєте масив покажчиків, ви можете змінювати результати безпосередньо в масиві без використання індексу, тут є приклад play.golang.org/p/_Vx7ONLDJs
notzippy

rangeпрацює нормально і повертає те, що ви помістили всередину фрагмента. Тут значення типу MyStruct(що є типом значення) знаходяться всередині зрізу. Натомість ми могли б помістити покажчики типу *MyStructвсередину зрізу. Якщо вам це абсолютно потрібно, щоб працювати так, як є, ви можете використовувати індекси замість значень, які повертає range.
Kaveh Shahbazian

Відповіді:


123

Коротка і пряма відповідь: ні, використовуйте індекс масиву замість значення

Отже, наведений вище код стає:

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
І, звичайно, якщо ви повторно отримати доступ array[idx]ви можете замість цього вибрати , щоб e := &array[idx]у верхній частині для циклу , а потім використовувати e.field1, e.field2і т.д. , які ближче нагадує ОП , можливо, хотів (тільки з двома лініями замість одного).
Dave C

16
Ви можете скинути , _повністю -for idx := range array
Сем Толіман

0

Це вже було сказано в коментарях, але для тих, хто шукає відповіді відразу, ось як можна досягти очікуваного результату, використовуючи зріз покажчиків та вносячи якнайменше зміни до вихідного коду.

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

}

Ось він на дитячому майданчику


2
Справа в тому, що покажчик корисний лише для використання цього діапазону. Я волів би додати e := &array[idx]всередині кожного діапазону, що має цей вказівник, до вказівника ...
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("--")
    }
}

Здається, це нічого не додає до існуючої прийнятої відповіді (опублікованої 6 років тому).
Британці
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.