小编典典

迭代时更改值

go

假设我有以下几种类型:

type Attribute struct {
    Key, Val string
}
type Node struct {
    Attr []Attribute
}

我想迭代节点的属性以更改它们。

我本来希望能够做到:

for _, attr := range n.Attr {
    if attr.Key == "href" {
        attr.Val = "something"
    }
}

但是由于attr不是指针,所以这行不通,我必须这样做:

for i, attr := range n.Attr {
    if attr.Key == "href" {
        n.Attr[i].Val = "something"
    }
}

有没有更简单或更快速的方法?是否可以直接从中获取指针range

显然,我不想仅仅为了迭代而更改结构,更冗长的解决方案不是解决方案。


阅读 305

收藏
2020-07-02

共1个答案

小编典典

不,您想要的缩写是不可能的。

原因是range从您要遍历的切片中复制值。关于范围规范说:

Range expression                          1st value             2nd

value (if 2nd variable is present)
array or slice a [n]E, *[n]E, or []E index i int a[i]
E

因此,范围a[i]用作数组/切片的第二个值,这实际上意味着该值已被复制,从而使原始值不可触摸。

下面的代码演示了此行为:

x := make([]int, 3)

x[0], x[1], x[2] = 1, 2, 3

for i, val := range x {
    println(&x[i], "vs.", &val)
}

该代码为您打印出范围中的值和切片中的实际值的完全不同的内存位置:

0xf84000f010 vs. 0x7f095ed0bf68
0xf84000f014 vs. 0x7f095ed0bf68
0xf84000f018 vs. 0x7f095ed0bf68

因此,您唯一可以做的就是使用指针或索引,正如jnml和peterSO所建议的那样。

2020-07-02