当将指针设置为nil时,结构体指针字段不会改变。

huangapple go评论87阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2022年11月15日 01:29:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/74435634.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定