假设我有这些类型:
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
获取指针?
显然,我不想仅仅为了迭代而更改结构,更冗长的解决方案不是解决方案。
最佳答案
不,你想要的缩写是不可能的。
这样做的原因是 range
从您正在迭代的 slice 中复制值。
specification about 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
因此,range 使用 a[i]
作为数组/slice 的第二个值,这实际上意味着
复制值,使原始值不可触及。
following code 演示了此行为:
x := make([]int, 3)
x[0], x[1], x[2] = 1, 2, 3
for i, val := range x {
println(&x[i], "vs.", &val)
}
该代码为您打印范围内的值和实际值的完全不同的内存位置 slice 中的值:
0xf84000f010 vs. 0x7f095ed0bf68
0xf84000f014 vs. 0x7f095ed0bf68
0xf84000f018 vs. 0x7f095ed0bf68
所以你唯一能做的就是使用指针或索引,正如 jnml 和 peterSO 已经提出的那样。
关于arrays - 迭代时更改值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56925349/