范围引用代替值


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

这里“ field”没有被修改,因为range发送了field的副本,我是否必须使用index还是有其他方法可以修改值?

谢谢阅读。



1
您可以使用的指针数组MyType吗?
nvcnvn

是的,如果您使用指针数组,则可以在不使用索引的情况下直接在数组中修改结果,这里有一个示例play.golang.org/p/_Vx7ONLDJs
notzippy 2014年

range工作正常,它会返回您放入切片中的内容。这里,类型MyStruct的值(这是一个值类型)位于切片内。相反,我们可以将类型的指针*MyStruct放在切片中。如果您绝对需要它按原样工作,则可以使用索引来代替所返回的值range
卡夫·沙巴兹安

Answers:


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]在for循环的顶部使用e.field1,然后使用e.field2,等等,这与OP可能想要的更为相似(只是用两行而不是一行)。
Dave C

16
您可以, _完全删除for idx := range array
Sam Toliman

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年前发布)添加任何内容。
英国佬
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.