I seem to have a misunderstanding with function named types and casting.

blov · · 920 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I am working on a scripting engine for personal use, dealing with Lua. Given the nature of communicating with a dynamically typed language I’m building the engine to some runtime casting and some reflection.</p> <p>For this specific case, I’m combining the [gopher-lua](github.com/yuin/gopher-lua) and [gopher-luar](github.com/layeh/gopher-luar) libraries to accomplish this. The <code>gopher-lua</code> package provides a strict method for defining Go functions that can be called/accessed from Lua, they take an LState and return an int. I wrapped this with a similar style that takes my scripting engine and returns an int, and created a named type for this.</p> <pre><code>type ScriptFunction func(*Engine) int </code></pre> <p>(I realize, at this point, this whole project could probably fall under the Inner-Platform effect, so no need to point that out)</p> <p>This was before I integrated with <code>gopher-luar</code> which provides an even more dynamic way of introducing functions (you can just pass in whatever function you want and it maps the arugments for you). So when making my engine method that allows moving a function to Lua I modified it to take an interface and handle either my custom function type or an interface and let luar take care of the interface. So I noticed that this doesn’t work (even though I would expect it too).</p> <pre><code>type Fn func(int) int someFunc := func(i int) int { return i } var iface interface{} = someFunc _, ok := iface.(Fn) // ok is false here, shouldn’t it be true? </code></pre> <p>I figured, “Okay, the variable is auto assigned a type. So it’s type is <code>func(int) int</code>” I tested this with a cast to this type, success. “Okay, so if I manually set the type…”</p> <pre><code>var someFunc Fn = func(i int) int … </code></pre> <p>Then did the rest, still nothing. So it would seem I have to actually force the cast to <code>func(int) int</code> instead of being able to get a type via casting to valid named types.</p> <p>Is this expected? Am I missing something with named types?</p> <hr/>**评论:**<br/><br/>okaydave: <pre><p>Yes, this is expected. The type assertion is saying that <code>someFunc</code> is a <code>Fn</code>. But it&#39;s not yet, it&#39;s just a <code>func(int) int</code>.</p> <p>However you can say something like <code>foo := Fn(someFunc)</code> to make it into <code>Fn</code>: <a href="http://play.golang.org/p/DiHSoPtjKa">http://play.golang.org/p/DiHSoPtjKa</a></p></pre>izuriel: <pre><p>Thanks for the reply. I see now that despite thinking I was aware that it was not a type alias I still tried to use it that way. </p></pre>dwevlo: <pre><p>Just to add a little. The spec says:</p> <blockquote> <p>Two named types are identical if their type names originate in the same TypeSpec. A named and an unnamed type are always different. Two unnamed types are identical if the corresponding type literals are identical, that is, if they have the same literal structure and corresponding components have identical types.</p> </blockquote> <p><code>Fn</code> is not a type alias, it&#39;s a new type, so it&#39;s always going to be considered different by the language. The two are however mutually assignable:</p> <blockquote> <p>A value x is assignable to a variable of type T (&#34;x is assignable to T&#34;) in any of these cases: x&#39;s type is identical to T. x&#39;s type V and T have identical underlying types and at least one of V or T is not a named type.</p> </blockquote> <p>So you could use reflection:</p> <pre><code>type Fn func(int) int id := func(x int) int { return x } var zeroFn Fn log.Println(reflect.TypeOf(id).AssignableTo(reflect.TypeOf(zeroFn))) </code></pre> <p>If that&#39;s true then you know you have a <code>func(int)int</code> even if it was given a different name.</p></pre>izuriel: <pre><p>Thanks for the insight. This post was great. </p> <p>I definitely <em>knew</em> that it wasn&#39;t a type alias but for some reason was still trying to <em>use</em> it like one. </p> <p>I try not to use reflection unless I really have too (I&#39;ll leave that to <code>luar</code>). I just use the actual type for the check. </p></pre>

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

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