如果这是一个微不足道的问题,我是新来的,请原谅我。我想迭代一段帖子并增加每个帖子 func incrementViews(posts []model.Post) []model.Post {
for _, v := range posts {
v.Views++
fmt.Println(v.Views) //Views incremented by 1
}
return posts
}
incrementViews(posts) //Views not changed
的值:
incrementViews(posts)
打印值已更改,但当我调用*
时,返回的值不变。
我尝试使用&
的{{1}}来解决这个问题,但可能无法做到这一点,因为我来自Python背景,并且已经忘记了通过指针和值移动变量。
答案 0 :(得分:1)
问题中的代码是更新局部变量v
。将切片更改为* model.Post或使用索引运算符更新切片中的值。前者需要更改呼叫者。
func incrementViews(posts []*model.Post) []*model.Post {
for _, v := range posts {
v.Views++
}
return posts
}
func incrementViews(posts []model.Post) []model.Post {
for i := range posts {
posts[i].Views++
}
return posts
}
修改强>
这两种方法都有效,请参见此处:https://play.golang.org/p/90BNOFYaKL
答案 1 :(得分:1)
range
表达式返回slice元素的副本。因此,在迭代时想要修改切片元素时应该非常小心。
切片或数组上的range
表达式将第一个参数作为索引返回,将第二个参数作为该索引处元素的副本返回。在您的示例中,您正在修改范围返回的副本,因此无法在原始切片元素中进行修改。
您需要更改的是,使用[
索引]
引用切片名称,以便实际引用切片中的原始元素,从而可以修改原始切片元素。请参阅jeevatkm给出的工作示例中的second approach。
另一个选项是使用切片地址,在这种情况下,您可以引用范围返回的值,因为即使它是副本,它也是地址位置的副本,它仍然指向原始元素。请参阅jeevatkm给出的工作示例中的第一种方法。