<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's Assignable.</p>
<hr/>**评论:**<br/><br/>DenzelM: <pre><p>You'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're reaching into the interface, <em>converting</em> it'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't) what you're doing would be equivalent to say:</p>
<p><code>
dynamic_cast<map[string]interface{}>(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 "return value" 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'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>
Why are type defs not assignable to each other yet AssignableTo and Convert work?
xuanbao · · 331 次点击这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
0 回复
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传