英文:
Go loop pointer changes
问题
我正在使用Go语言中的for range
循环来遍历一个结构体切片。
在每次循环中,我将当前项的指针赋值给一个变量。
我对于为什么指针在下一次循环中会改变值感到困惑。
例如,这段代码:
package main
import "fmt"
type t struct {
val int
}
func main() {
l := []t{{1}, {2}}
var p *t
for _, i := range l {
fmt.Println("begin", p)
p = &i
fmt.Println("end", p)
}
}
我期望的输出是:
begin <nil>
end &{1}
begin &{1}
end &{2}
但实际输出是:
begin <nil>
end &{1}
begin &{2}
end &{2}
作为参考,我在实际代码中,在循环期间检查一个条件,并返回当前项和前一项。所以我试图保存一个指向它的指针,以便在下一次迭代中也能访问到前一项。
英文:
I am using a for range
loop in Go to iterate through a slice of structs.
In each loop, I a pointer to the current item to a variable.
I am confused why the pointer changes value in the next loop.
For example this code:
package main
import "fmt"
type t struct {
val int
}
func main() {
l := []t{{1}, {2}}
var p *t
for _, i := range l {
fmt.Println("begin", p)
p = &i
fmt.Println("end", p)
}
}
I would expect to produce:
begin <nil>
end &{1}
begin &{1}
end &{2}
But actually does:
begin <nil>
end &{1}
begin &{2}
end &{2}
For reference, in my actual code, I am checking for a condition during the loop, and returning the current item and previous one. So I am trying to save a pointer to it, so that in the next iteration it will have access to the previous as well.
答案1
得分: 1
根据Tim的评论,似乎你可以在每次循环中复制值,而不是指针,并在之后解引用它。
package main
import "fmt"
type t struct {
val int
}
func main() {
l := []t{{1}, {2}}
var p t
var i t
for _, i = range l {
fmt.Println("begin", &p)
p = i
fmt.Println("end", &p)
}
}
英文:
Building off Tim's comment, it seems like you can copy the value on each loop, instead of the pointer, and dereference it after.
package main
import "fmt"
type t struct {
val int
}
func main() {
l := []t{{1}, {2}}
var p t
var i t
for _, i = range l {
fmt.Println("begin", &p)
p = i
fmt.Println("end", &p)
}
}
答案2
得分: 1
另一种选择是通过使用索引来获取当前项的指针:
package main
import "fmt"
type t struct {
val int
}
func main() {
l := []t{{1}, {2}}
var p *t
for index, _ := range l {
fmt.Println("begin", p)
p = &l[index]
fmt.Println("end", p)
}
}
另外一个选项是通过使用索引来获取当前项的指针:
package main
import "fmt"
type t struct {
val int
}
func main() {
l := []t{{1}, {2}}
var p *t
for index, _ := range l {
fmt.Println("begin", p)
p = &l[index]
fmt.Println("end", p)
}
}
英文:
Another option is to get the pointer to the current item by using the index:
package main
import "fmt"
type t struct {
val int
}
func main() {
l := []t{{1}, {2}}
var p *t
for index, _ := range l {
fmt.Println("begin", p)
p = &l[index]
fmt.Println("end", p)
}
}
答案3
得分: 1
问题在于你取的是循环/范围变量的地址,而不是切片中项的地址。然而,你只是给自己增加了很多不必要的工作。首先,为什么不使用i, v := range
或者更好的是i, _ :=
,然后你可以使用i-1
来获取前一个项?其次,即使你想将其保存在指针中,仍然使用这种语法,然后赋值p = &l[i]
,这样你就有了切片中项的地址,而不是循环/范围变量的地址。
人们在明显更好使用索引的情况下过于急于使用for/each风格的结构...如果你想在每次迭代中使用索引-1,使用索引应该是你首选的方法。
英文:
The problem is that you're taking the address of the loop/range variable and not the address of the item in slice. However, you're just making a lot of unnecessary work for yourself. For one, why don't you use the i, v := range
or better yet i, _ :=
and then you can do i-1
to get the previous item? Secondly, even if you want it saved in a pointer, still use this syntax and then assign p = &l[i]
so you have the address of the item in the slice rather than the address of the loop/range variable.
People are way too eager to use for/each style constructs when it's obviously better to work with the index... If you want index-1 on every iteration, using the index should be your go to way of doing that.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论