英文:
When setting the pointer to nil, struct pointer field doesn't change
问题
我有这段代码:
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
}
如你所见,x.y
是一个 *X
类型。为什么将 x1
设置为 nil
后,x2.y
的值不变为 nil
呢?如果我的问题很愚蠢,请原谅。
这是 Go Playground 上代码的链接。
英文:
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.
答案1
得分: 3
x1
是一个指向类型为X
的{y:nil}
的指针。
x2.y
也是一个指向同一个{y:nil}
的指针。所以当你设置x1=nil
时,x1
变成了一个空指针,而x2.y
仍然指向同一个{y:nil}
对象。
英文:
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.
答案2
得分: 1
不,x2.y
仍然指向你分配给 x1
的对象。这就是你的代码基本上在做的事情:
内存中的对象
| 内存地址 | 值 |
| 0xDEADBEEF | X{y: nil } |
| 0x1BADB002 | X{y: 0xDEADBEEF } |
|--------------|-------------------|
在你的代码中:
| 变量 | 值 |
| x1 | 0xDEADBEEF |
| x2 | 0x1BADB002 |
所以现在通过 x1 = nil
,你只是改变了一个变量的值:
| 变量 | 值 |
| x1 | nil |
| x2 | 0x1BADB002 |
x2
仍然指向内存中的一个值,该值又指向内存中的另一个对象。Go 运行时会识别到这一点,并且会看到存储在 0xDEADBEEF
中的对象仍在使用中,因此不会释放内存。
更直观的表示方式可能是这样的:
+-----------+(0xDEADBEEF)
| X{y: nil} |
+-----------+
/\ /\
||-------||--> 两者指向同一个对象
+----+ ||
| x1 | ||
+----+ ||
+----------||------+(0x1BADB002)
| X{y: 0xDEADBEEF} |
+------------------+
/\
|| 指向这个对象
+----+
| x2 |
+----+
通过设置 x1 = nil
,你所做的只是切断了变量 x1
与实际内存中的对象之间的链接。x2.y
与该对象之间的链接仍然存在。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论