这是我学习go过程中最困惑的地方。我们都知道方法T
只影响副本T
,以及方法*T
会影响实际数据T
.
为什么方法上T
也可以使用*T
,但不允许相反的情况?那么,你能给我一个例子(或原因)说明为什么他们不允许方法*T
被使用T
?
这种设计的优点和缺点是什么?
这里有很多答案,但没有一个回答为什么会出现这种情况。
首先,我们假设您有一个 *T 并想要调用一个采用 T 的方法。为此,您所需要做的就是将 *yourT (其中 * 用于取消引用指针)传递给函数。这肯定是可能的,因为您只是在已知位置复制内存块。
现在假设您有一个 T 并且想要一个 *T。您可能认为只需执行 &yourT 即可获取其地址。但生活并不总是那么简单。并不总是有静态地址可供使用。
From the spec:
对于 T 类型的操作数 x,地址运算 &x 生成一个指向 x 的 *T 类型的指针。操作数必须是可寻址的,即变量、指针间接或切片索引操作;或可寻址结构操作数的字段选择器;或可寻址数组的数组索引操作。作为可寻址性要求的一个例外,x 也可以是(可能带括号的)复合文字。
您可能会问自己为什么他们会对获取内存地址施加这些任意限制。每个变量必须有some内存地址,对吗?虽然这是事实,但优化可能会使这些地址变得相当短暂。
例如,假设变量位于映射内:
res := TMap["key"].pointerMethod()
在这种情况下,您实际上是在说您希望将指向内存的指针保存在映射内。这将迫使 Go 的每个实现都以内存地址保持静态的方式实现映射。这将严重限制运行时的内部结构,并使实现者在构建高效映射时的自由度大大降低。
还有其他示例,例如函数返回或接口,但您只需要一个示例即可证明该操作不保证可行。
最重要的是,计算机内存并不简单,虽然您可能想说“只需获取地址”,但它并不总是那么简单。获取保证静态的地址并不总是可行的。因此,您不能保证 T 的任何实例都可以转换为指针并传递给指针方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)