Home > front end >  GoLang pointers are behaving wierd
GoLang pointers are behaving wierd

Time:01-20

Why does changing node2.Next affects node2 in the below code?

import "fmt"

type ListNode struct {
    Val int
    Next *ListNode
}


func main() {
    node1 := ListNode{Val:10 , Next:nil}
    node2 := ListNode{Val:100 , Next:&node1}
    temp := node2

    if(temp == node2){
        fmt.Println("Equalssss1")
    }
    node2.Next = &(ListNode{1 , nil})
    if(temp == node2){
        fmt.Println("Equalssss2")
    }
}

Basically why doesn't "Equalssss2" doesn't get printed? I feel since node2.Next is changed but not node2, node2 should be equal to temp Why isn't it the case?

CodePudding user response:

There are no misbehaving pointers in your code. I suspect that what you think are pointers are not actually pointers, hence your confusion.

In your code node1 and node2 are ListNode structs, i.e. _value types. When you assign node2 to temp, temp then holds a copy of node2, not a pointer or reference to it.

In Go, (in simple terms) two struct values are equal if they of the same type and consist of comparable fields that all evaluate as equal.

When you initially compare node2 and temp the values of all of the fields in each of the two values are the same, therefore temp == node2 evaluates true.

You then change the Next field of node2, therefore when you again compare temp == node2 they are no longer equal since they differ in the value of that field.

To get the behaviour you are expecting, node1 and node2 would need to be pointers to a ListNode:

type ListNode struct {
    Val  int
    Next *ListNode
}

func main() {
    node1 := &ListNode{Val: 10, Next: nil}
    node2 := &ListNode{Val: 100, Next: node1}
    temp := node2

    if temp == node2 {
        fmt.Println("Equalssss1")
    }

    node2.Next = &(ListNode{1, nil})
    if temp == node2 {
        fmt.Println("Equalssss2")
    }
}

temp is now also a pointer to a ListNode, rather than a copy of the ListNode value; temp is initialised to reference the same ListNode that node2 references. That is, the pointers temp and node2 are equal; they both point to the same ListNode.

Now, when you change node2.Next, this doesn't affect the fact that temp is still just a copy of the node2 pointer and since neither the value of node2 itself (the pointer) nor temp have changed, they are still equal.

i.e. if you were using pointers, your code would behave as expected. If you think that pointers are behaving "weirdly" it is because, in this instance, you are not actually using pointers. :)

CodePudding user response:

As the commenters on your question are trying to point out, nothing at all weird is happening here. Add this after your first conditional:

fmt.Printf("temp is at %p and temp.Next is at %p\nnode2 is at %p and node2.Next is at %p\n", &temp, temp.Next, &node2, node2.Next)

this will output:

temp is at 0xc00009e240 and temp.Next is at 0xc00009e220
node2 is at 0xc00009e230 and node2.Next is at 0xc00009e220

and try adding this line after your second conditional:

fmt.Printf("temp.Next has Val: %d\nnode2.Next has Val: %d\n", temp.Next.Val, node2.Next.Val)

which will output:

temp.Next has Val: 10
node2.Next has Val: 1

You can see the result here.

node2 and temp point to different objects, both of which have the same field values until you modify node.Next. Your assignment temp := node2 makes creates a new instance of the struct type and copies in the values from the source object. It does not create a pointer to the node object - if it had, then changing node2.<field> would also change temp.<field>. This is made slightly confusing by the fact that, in go (unlike in say C) you do not need to dereference the pointer/use different accessor syntax to access struct fields, so the following would be completely fine:

temp := &node2
node2.Val = 500
fmt.Printf("%d == %d\n, temp.Val, node2.Val)

In the end, everything here is happening exactly as one would expect. Put another way, your first conditional is checking equality but not identity. Different objects (identity) with the same values (equality).

  • Related