golang在T和* T上区分方法集的原因是什么? [英] What is the reason golang discriminates method sets on T and *T?

查看:127
本文介绍了golang在T和* T上区分方法集的原因是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在学习过程中,这是我最迷惑的地方。我们都知道 T 上的方法仅影响 T 的副本,而 * T 会影响 T 上的实际数据。



为什么 T 也可以被 * T 使用,但是相反是不允许的?那么,你能给我一个例子(或理由),说明为什么他们不允许 * T T

这个设计的优点和缺点是什么?

解决方案



首先让我们看看你有* T并想打电话一个采用T的方法。为此,您需要做的就是将* yourT(其中*用于取消引用指针)传递给该函数。这保证是可能的,因为你只是在已知的位置复制内存块。



现在让我们说你有一个T并且想要一个* T。你可能会想,你可以做& yourT并得到它的地址。但生活并不总是那么简单。并不总是有一个静态地址。






来自


对于T类型的操作数x,地址操作& x产生一个类型为* T的指针给x。操作数必须是可寻址的,即变量,指针间接或片段索引操作;或可寻址结构操作数的字段选择器;或可寻址阵列的数组索引操作。作为寻址能力要求的一个例外,x也可以是(可能加括号的)复合文字。

您可能会问自己为什么他们会在获取内存地址时放置这些任意限制。每个变量都必须有一些内存地址,对吧?虽然这是真的,但优化可以使这些地址变得短暂。

例如,假设变量位于地图内:

  res:= TMap [key]。pointerMethod()

在这种情况下,您正在有效地说您需要一个指向内存的指针。这将强制Go的每个实现都以内存地址保持静态的方式实现映射。这会严重限制运行时的内部结构,并给执行者构建高效映射的自由度少得多。

还有其他例子,例如函数返回或接口,但你只需要一个例子来证明操作不能保证是可能的。






底线是计算机内存这并不简单,虽然你可能想说只是拿地址,但并不总是那么简单。采取保证是静态的地址并不总是可能的。因此,你不能保证T的任何实例可以变成指针并传递给指针方法。


This is where confuses me the most while learning go. We all know that methods on T only affect the copy of T, and methods on *T will affect the actual data on T.

Why does methods on T can also be used by *T, but the opposite is not allowed? So,can you give me an example(or reason) on why they do not allow method on *T be used by T?

What is the pros and cons of this design?

解决方案

There are many answers here, but non of them answer why this is the case.

First lets take the case of you having a *T and wanting to call a method which takes T. To do this, all you need to do is pass *yourT (where * is being used to dereference the pointer) to the function. This is guaranteed to be possible because you are just copying blob of memory at a known location.

Now lets say you have a T and want a *T. You may be thinking that you could just do &yourT and get its address. But life isn't always so simple. There isn't always a static address to take.


From the spec:

For an operand x of type T, the address operation &x generates a pointer of type *T to x. The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal.

You may be asking yourself why they would place these arbitrary restrictions on getting a memory address. Every variable must have some memory address, right? While this is true, optimizations can make those addresses rather ephemeral.

For example, lets say the variable was inside a map:

res := TMap["key"].pointerMethod()

In this case, you are effectively saying you want a pointer to memory being held inside a map. This would force every implementation of Go to implement map in such a way that memory addresses remain static. This would severely limit the internal structures of the runtime and give the implementers much less freedom in building an efficient map.

There are other examples such as function returns or interfaces, but you only need one example to prove that the operation is not guaranteed to be possible.


The bottom line is that computer memory isn't simple and while you may want to say "just take the address", it isn't always that simple. Taking an address that is guaranteed to be static isn't always possible. Therefore, you can't guarantee that any instance of T may be turned into a pointer and passed to a pointer method.

这篇关于golang在T和* T上区分方法集的原因是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆