<p>Hi all. According to the language specification, <code>*T</code>'s method set contains the method set of <code>T</code>. By that logic, shouldn't <code>**T</code>'s method set contain the method set of <code>*T</code> (and therefore of <code>T</code>)?. But it seems if I have a value of type <code>**T</code>, I cannot call any methods on it (neither those declared on <code>*T</code> nor <code>T</code>). Is there some rule I'm not noticing? Thanks!</p>
<hr/>**评论:**<br/><br/>willglynn: <pre><p>The spec says:</p>
<blockquote>
<p>The method set of the corresponding pointer type <code>*T</code> is the set of all methods declared with receiver <code>*T</code> or <code>T</code> (that is, it also contains the method set of <code>T</code>).</p>
</blockquote>
<p>This rule could be read as applying to arbitrary layers of indirection, or it could be read as applying to a single layer of indirection.</p>
<p>Automatic double-dereferencing is now considered a bug and was <a href="https://golang.org/doc/go1.4#methodonpointertopointer" rel="nofollow">fixed in Go 1.4</a>, indicating that the second interpretation is correct.</p>
<p>If this change broke your code, dereference once using <code>*</code> (thus converting <code>**T</code> into <code>*T</code>) and call whatever methods you want.</p></pre>SteveMcQwark: <pre><p>The relevant section of the spec is:</p>
<p><a href="https://golang.org/ref/spec#Selectors" rel="nofollow">https://golang.org/ref/spec#Selectors</a></p>
<p>Specifically:</p>
<blockquote>
<p>For a value x of type T or *T <strong>where T is not a pointer or interface type</strong>, x.f denotes the field or method at the shallowest depth in T where there is such an f.</p>
</blockquote>
<p>The spec should probably specify that the T in </p>
<blockquote>
<p>The method set of any other type T consists of all methods declared with receiver type T.</p>
</blockquote>
<p>should be a <em>named</em> type. The fact that it can't be a pointer type would then be implied by:</p>
<blockquote>
<p>The receiver is specified via an extra parameter section preceding the method name. That parameter section must declare a single non-variadic parameter, the receiver. Its type must be of the form T or *T (possibly using parentheses) <strong>where T is a type name</strong>. The type denoted by T is called the receiver base type; <strong>it must not be a pointer or interface type</strong> and it must be declared in the same package as the method.</p>
</blockquote>
<p>Honestly, the language around methods has always been difficult to get right because of the interactions between selectors, method sets, and method promotion from anonymous fields.</p></pre>izuriel: <pre><p>I think the first part you emphasized perfectly explains it. </p>
<blockquote>
<p>For a value x of type T or *T <strong>where T is not a pointer or interface type</strong></p>
</blockquote>
<p>In his question he asks about **T which could be simplified to just *K where K is *T and if we then apply we see that K is a pointer which is not allowed. I think the language is perfectly clear. </p>
<p><strong>edit</strong> fix phone grammar. </p></pre>SteveMcQwark: <pre><p>Yes, but that's the section on selectors. Method sets don't explicitly depend on selectors in the spec (though conceptually they fall out of the combination of selectors and addressability). In order for the method set spec to be complete, it needs to specify that T is a named type or else tie it to selectors in some way. I think the language around method sets was changed in order to accommodate unnamed struct types with promoted methods, but it went too far in the other direction.</p></pre>fortyninezeronine: <pre><p>You need to dereference **T:</p>
<p><a href="https://play.golang.org/p/BSC-GM8t2g" rel="nofollow">https://play.golang.org/p/BSC-GM8t2g</a></p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
0 回复
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传