I have this code:
type X struct {
y *X
}
func main() {
x1 := &X{y: nil}
x2 := &X{y: x1}
fmt.Println(x1 == x2.y)
// true
x1 = nil
fmt.Println(x1 == nil)
fmt.Println(x2.y == nil)
// true
// false
}
As you can see x.y
is a *X
.
Why after setting x1
to nil
. The value of x2.y
doesn't become nil
?
Sorry if my question is so silly.
Here is the link of the code in Go playground.
CodePudding user response:
x1
is a pointer pointing to an {y:nil}
of type X
.
x2.y
is also a pointer pointing to the same {y:nil
}. So when you set x1=nil
, x1
becomes a pointer that is nil, and x2.y
is still pointing to the same {y:nil}
object.
CodePudding user response:
No, x2.y
will still point to the object you assigned to x1
. This is what your code is basically doing:
Objects in memory
| memory address | value |
| 0xDEADBEEF | X{y: nil } |
| 0x1BADB002 | X{y: 0xDEADBEEF } |
|----------------|-------------------|
In your code:
| variable | value |
| x1 | 0xDEADBEEF |
| x2 | 0x1BADB002 |
So now by doing x1 = nil
, all you do is changing the value of a variable:
| variable | value |
| x1 | nil |
| x2 | 0x1BADB002 |
x2
still points to a value in memory, which in turn points to another object in memory. The go runtime recognises this, and sees that the object stored in 0xDEADBEEF
is still in use, so it doesn't release the memory.
A more visual representation would be something like this:
----------- (0xDEADBEEF)
| X{y: nil} |
-----------
/\ /\
||-------||--> Both point to the same object
---- ||
| x1 | ||
---- ||
----------||------ (0x1BADB002)
| X{y: 0xDEADBEEF} |
------------------
/\
|| points to this object
----
| x2 |
----
By setting x1 = nil
, all you've done is severed the link between the variable x1
and the actual object in memory. The link between x2.y
and that object still exists.