Reference 围棋:你能用一个切片的范围,但得到参考?(迭代)

Reference 围棋:你能用一个切片的范围,但得到参考?(迭代),reference,iteration,range,go,Reference,Iteration,Range,Go,假设我要更改数组中所有对象的值。 我更喜欢范围语法,而不仅仅是为循环命名 所以我试着: type Account struct { balance int } type AccountList []Account var accounts AccountList ... .... // to init balances for _,a := range( accounts ) { a.balance = 100 } 这不起作用,因为a是AccountList中条目的副本,因此我们

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

所以我试着:

type Account struct {
   balance int
}
type AccountList []Account
var accounts AccountList
...
....
// to init balances
for _,a := range( accounts ) {
    a.balance = 100
}
这不起作用,因为a是AccountList中条目的副本,因此我们只更新副本

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

for a := range( accounts ) {
  accounts[a].balance = 100
}
但该代码在for循环中有一个额外的查找


有没有一种方法可以执行迭代器来获取对AccountList中结构的引用?

只要让AccountList为[]*Account即可。然后,您将获得指向范围内每个帐户的指针。

问题是,通过使用第一个for/range循环,您将获得变量
a
中的struct by值。您使用的第二个for/range循环通过直接访问片中的内存来解决问题

但是,您指出在第二个for循环中发生了“额外”查找是错误的。循环条件只是检查切片的长度并增加一个计数器,直到它到达末端。
accounts[a]
表达式将实际执行数组查找并直接操作内存。如果有什么区别的话,第二个for循环转换为更少的指令,因为它没有首先将struct by value的内容复制到变量中

我想你担心的是每次都要引用
账户[I]
。如果要在for循环中对帐户执行多个操作,我认为最好的解决方法如下:

for i := range accounts {
    a := &accounts[i]
    a.balance = 100
    // manipulate account A further...
}

正如Mue所建议的,另一种可能的解决方案是简单地使用切片保持指针。这两种方法都有好处,但无论你是C还是围棋,困境都是一样的。Go只是有一点语法上的甜点。

有没有理由
AccountList
不能成为
[]*账户
?我想这在大多数情况下是有道理的。在垃圾回收器或内存缓存上使用[]帐户可能更容易,但这可能只是在性能调整期间值得进行的更改。您可以执行以下操作:accounts[i]。balance=100Yes。我认为直接使用切片通常要好得多,或者Mue的解决方案是使切片保持指针。但是,正如我所说的,我发布的代码片段甚至还有一些优点。例如,我使用了与此类似的设置来创建一个节点池,以将数据保存在内存中类似的位置。Go给你控制权,让你用记忆做你想做的事;你只需要发现你想要什么。:)