为什么普通的for循环允许将值分配给struct字段,而for范围在Golang中不起作用? [重复]

问题描述 投票:0回答:3

使用范围:

for _, acc := range accounts{
        accDetails, _ := repo.GetAccountDets(ctx, acc.number, acc.status)
        acc.Details = *accDetails
}

以上代码无效。

但是,以下工作。

for i:=0; i < len(accounts); i++ {
       accDetails, _ := repo.GetAccountDets(ctx, accounts[i].number, accounts[i].status)
       accounts[i].Details = *accDetails
}

为什么?我认为在此处添加帐户结构详细信息没有任何价值

for-loop go range for-range
3个回答
2
投票

我想说,这个问题超出了Golang的范围,它与基础数据结构或容器有关。在第二种情况下,您似乎已经知道容器'len(accounts)'的长度,因此它是可以顺序访问的固定存储。并非总是如此。如果帐户是一个不断增加(或减少)的容器怎么办?您如何计算该容器的长度。取而代之的是,您所要问的是“帐户”中提供的内容是什么给我。你打算怎么做?好吧,您设置了一个虚拟变量,该变量仅被允许访问或模仿容器的内容(并因此带有所有属性或“结构字段”)。另外,出于对只读的考虑,可以在后续代码中适当考虑范围,将其抛出。


0
投票

在形式为for i,v:=range slice {...}的for循环中,变量v与要循环的元素具有相同的类型,并且每次迭代都将切片/映射中的下一项内容复制到v。因此,如果v是一个结构,并且您为结构成员分配值,则永远不会将那些值复制回复制它的切片中。如果slice是指向struct的指针的切片,则v是指向struct的指针的副本,并且您对v的成员所做的更改将反映在原始slice元素上。解决此问题的一种方法是使用索引:

for i:=range accounts {
   accounts[i].Field=value
}

0
投票

每当在for循环中初始化变量时,该变量在本地仅限于for循环,在范围内,您将在acc变量中创建元素的副本

for _, acc := range accounts{
        accDetails, _ := repo.GetAccountDets(ctx, acc.number, acc.status)
        acc.Details = *accDetails
}

acc只是accounts中元素的本地副本,如果在accacc >>中添加任何内容,则不会影响accounts slice。

但是在您的另一个示例中..

for i:=0; i < len(accounts); i++ {
       accDetails, _ := repo.GetAccountDets(ctx, accounts[i].number, accounts[i].status)
       accounts[i].Details = *accDetails
}

您不是为帐户中的元素制作本地副本,而是通过accounts [i]

直接访问它们,这将更新accounts
切片。

如果您仍要使用范围,则可以仅使用索引。

for i := range accounts{
       accDetails, _ := repo.GetAccountDets(ctx, accounts[i].number, accounts[i].status)
       accounts[i].Details = *accDetails
}
© www.soinside.com 2019 - 2024. All rights reserved.