Why are type defs not assignable to each other yet AssignableTo and Convert work?

xuanbao · · 331 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Look at this <a href="https://play.golang.org/p/1dSqRYkg_c" rel="nofollow">snippet</a>, I define a type for map[string]interface. Using type assertion results in panic yet reflection works.</p> <p>Just seems like Go should be able to convert if it&#39;s Assignable.</p> <hr/>**评论:**<br/><br/>DenzelM: <pre><p>You&#39;re running into the difference between <a href="http://golang.org/ref/spec#Type_assertions" rel="nofollow">type assertions</a> and <a href="http://golang.org/ref/spec#Conversions" rel="nofollow">type conversions</a>. Their semantics are not the same. And as your example code proves you must <em>convert</em> the underlying type before you <em>assert</em> it because <code>Object</code> and <code>map[string]interface{}</code> are not the same type. <a href="http://golang.org/ref/spec#Type_identity" rel="nofollow">Type identity</a> tells us that:</p> <blockquote> <p>A named and an unnamed type are always different.</p> </blockquote> <p>Therefore <code>v.(map[string]interface{})</code> fails as per the semantics of <em>type assertion</em>:</p> <blockquote> <p>The notation x.(T) is called a type assertion. More precisely, if T is not an interface type, x.(T) asserts that the dynamic type of x is identical to the type T</p> </blockquote> <p>So, <code>map[string]interface{}</code> and <code>Object</code> must be identical... which they are not.</p> <p>Essentially, in your reflection example, you&#39;re reaching into the interface, <em>converting</em> it&#39;s type, and then coming back out and <em>asserting</em> that its type is equal to the one you just converted it to. </p> <p>So, if Go had a dynamic conversion of sorts like C++ (which it doesn&#39;t) what you&#39;re doing would be equivalent to say:</p> <p><code> dynamic_cast&lt;map[string]interface{}&gt;(v).(map[string]interface{}) </code></p></pre>maverickwoo: <pre><p>Expanding a little bit on the excellent explanation above, the following function will compile and run. I have explicitly declared a &#34;return value&#34; variable and use the long form var declaration to make the type change clearer.</p> <pre><code>func assignMapTypeAssertOK(v interface{}) map[string]interface{} { var rv Object = v.(Object) return rv } </code></pre> <p>The function argument <code>v</code> is of (static) type <code>interface{}</code>, and its dynamic type is <code>Object</code>. So the type assertion in the first line is ok and <code>rv</code> is a value of type <code>Object</code>.</p> <p>Then, since the named type <code>Object</code> and the unnamed type <code>map[string]interface{}</code> have the same underlying type, Go performs an implicit conversion at return.</p> <p>Note that the implicit conversion happens only when one of the equivalent types is unnamed. If you have another named type with the same underlying type, say <code>type Object2 map[string]interface{}</code>, then a value of type <code>Object</code> will not be implicitly converted to a value of type <code>Object2</code>. Instead you would explicitly convert the value to the latter type, such as:</p> <pre><code>func assignMapTypeAssertOK2(v interface{}) map[string]interface{} { var rv Object = v.(Object) var rv2 Object2 = Object2(rv) return rv2 } </code></pre> <p>Hope this helps!</p></pre>mgutz: <pre><p>Excellent. Thanks for the clarification.</p></pre>HectorJ: <pre><p>works like this : <a href="https://play.golang.org/p/3nvMp1rdm7" rel="nofollow">https://play.golang.org/p/3nvMp1rdm7</a></p> <p>assert to <code>Object</code> first, then cast to <code>map[string]interface{}</code></p></pre>mgutz: <pre><p>It&#39;s just an <code>interface{}</code> value to the function. It can be called from any package. <code>Object</code> is the type in the playground to reproduce the issue. The real package has no idea of <code>Object</code>.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

331 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传