Pointer to the loop variable

80 views
Skip to first unread message

Tong Sun

unread,
Sep 10, 2019, 3:13:40 PM9/10/19
to golang-nuts
I'm experiencing a weird problem with my program and finally nail it down to what exactly went wrong, so that I can write a minimum program to duplicate it. See the following program:

package main


import (
 
"fmt"
)


type
Vertex struct {
 X
int
 Y
int
}


func main
() {
 vs
:= []Vertex{
 
Vertex{1, 2}, // has type Vertex
 
Vertex{X: 3}, // Y:0 is implicit
 
Vertex{},     // X:0 and Y:0
 
}


 fmt
.Printf("Vertex Slice %+v\n", vs)
 
var vp *Vertex = nil
 
for _, v := range vs {
 
if v.X == 3 {
 vp
= &v
 
}
 
}
 fmt
.Printf("Found: %+v\n", vp)
}


I was expecting that the found Vertex is "v.X == 3", however the result is not. 

- what exactly is causing the problem?
- how to fix it so that I got what I was looking for? 

Again, the snip is at

Thanks

burak serdar

unread,
Sep 10, 2019, 3:18:47 PM9/10/19
to Tong Sun, golang-nuts
On Tue, Sep 10, 2019 at 1:13 PM Tong Sun <sunto...@gmail.com> wrote:
>
> I'm experiencing a weird problem with my program and finally nail it down to what exactly went wrong, so that I can write a minimum program to duplicate it. See the following program:
>
> package main
>
>
> import (
> "fmt"
> )
>
>
> type Vertex struct {
> X int
> Y int
> }
>
>
> func main() {
> vs := []Vertex{
> Vertex{1, 2}, // has type Vertex
> Vertex{X: 3}, // Y:0 is implicit
> Vertex{}, // X:0 and Y:0
> }
>
>
> fmt.Printf("Vertex Slice %+v\n", vs)
> var vp *Vertex = nil
> for _, v := range vs {
> if v.X == 3 {
> vp = &v
> }
> }
> fmt.Printf("Found: %+v\n", vp)
> }
>
>
> https://play.golang.org/p/R645C5plojx
>
> I was expecting that the found Vertex is "v.X == 3", however the result is not.

Because you're keeping a pointer to the loop variable. v continues
changing after you store the address of it, so you get the latest
value of v. Instead, save a copy of v, or break the loop as soon as
what you're looking for is found:

if v.x==3 {
t:=v
vp=&t
}

>
> - what exactly is causing the problem?
> - how to fix it so that I got what I was looking for?
>
> Again, the snip is at
> https://play.golang.org/p/R645C5plojx
>
> Thanks
>
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/143205c1-2c86-4404-94d2-4182a6285e21%40googlegroups.com.

Yamil Bracho

unread,
Sep 10, 2019, 3:20:20 PM9/10/19
to golang-nuts
vp is taking the address of v, so when the loop ends, v is the last element in the slide and therefore *vp is {0,0}
Add a break to the condition when you assign vp, say

if v.X == 3 {
 vp
= &v
 break
}

HTH,
Yamil

Tong Sun

unread,
Sep 10, 2019, 3:29:50 PM9/10/19
to golang-nuts
 I can't break the loop immediately as my not-minimized real program use a double loop to find the closest item. That's the reason I using the pointer to track my finding...

if v.x==3 {
   t:=v
   vp=&t
}

 OK. will do that. thx

>
> - what exactly is causing the problem?
> - how to fix it so that I got what I was looking for?
>
> Again, the snip is at
> https://play.golang.org/p/R645C5plojx
>
> Thanks
>
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golan...@googlegroups.com.

Yamil Bracho

unread,
Sep 10, 2019, 3:37:22 PM9/10/19
to golang-nuts
Then turn vo into a Vertex variable, not a pointer

var vp Vertex = Vertex{}
...
if v.X == 3 {
   vp = v
  }

….

This time vp will be a copy of v,

Maybe you have to give some known values and exceptional case for your domain, I mean, vp  Vertex = { -1, -1} or any values your are 
positive does not exists because maybe {0,0} is good data.

HTH
PS: You can break nested loops from an inside loop using break [label]
Reply all
Reply to author
Forward
0 new messages