Go:您可以将范围与切片一起使用但获取引用吗?(迭代)

Jer*_*rks 4 iteration reference range go

假设我想更改数组中所有对象的值。我更喜欢范围语法,而不仅仅是命名为循环。

所以我尝试:

type Account struct {
   balance int
}
type AccountList []Account
var accounts AccountList
...
....
// to init balances
for _,a := range( accounts ) {
    a.balance = 100
}
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为 a 是 AccountList 中条目的副本,因此我们仅更新该副本。

这确实有效,因为我需要它:

for a := range( accounts ) {
  accounts[a].balance = 100
}
Run Code Online (Sandbox Code Playgroud)

但该代码在 for 循环内有一个额外的查找。

有没有办法创建一个迭代器来获取对 AccountList 中结构的引用?

Ros*_*ght 5

问题是,通过使用第一个 for/range 循环,您将在变量中按值获取结构体a。您使用的第二个 for/range 循环通过直接访问切片中的内存来解决问题。

但是,您指出第二个 for 循环内发生“额外”查找是错误的。循环条件只是检查切片的长度并增加计数器直到到达末尾。然后,该accounts[a]表达式将实际执行数组查找并直接操作内存。如果有的话,第二个 for 循环会转换为更少的指令,因为它不会首先将结构体的内容按值复制到变量中。

我认为您担心的是accounts[i]每次都必须参考。如果您想在 for 循环内对帐户执行多次操作,我认为解决它的最佳方法是这样的:

for i := range accounts {
    a := &accounts[i]
    a.balance = 100
    // manipulate account A further...
}
Run Code Online (Sandbox Code Playgroud)

正如 Mue 所建议的,另一种可能的解决方案是简单地让切片保存指针。这两种方法都有优点,但无论您使用 C 还是 Go,困境都是一样的。Go 只是多了一点语法糖。