Interfaces as map values?

agolangf · · 758 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hey Gophers, struggling Java programmer trying to make a <em>Go</em> of it here, I cannot figure out how interfaces work in Go!</p> <p>Could someone explain what I am doing wrong?</p> <p><a href="https://play.golang.org/p/blOfijx0S_">https://play.golang.org/p/blOfijx0S_</a></p> <p>Obviously this isn&#39;t the best use case but it illustrates my point. I hope...</p> <hr/>**评论:**<br/><br/>TicklyBaby: <pre><p>Add <code>&amp;</code> before Button on line 21:</p> <blockquote> <p>m[0] = &amp;Button{Name: &#34;Jim&#34;}</p> </blockquote> <p><a href="https://play.golang.org/p/IhIya-ZYpT">https://play.golang.org/p/IhIya-ZYpT</a></p></pre>twek: <pre><p>Thanks for getting it to compile! I&#39;m still fuzzy as to why that works... I know that the interface method is bound to a pointer so the first thing i tried was making a map of map[int]*Widgets but that took me down a whole other rabbit hole...</p></pre>hobbified: <pre><p>You have <code>func (b *Button) WidgetName() string</code>, that is, you defined a <code>WidgetName()</code> that can be called on a <code>*Button</code>.</p> <p>You also have <code>type Widget interface { WidgetName() string }</code>, which says that a <code>Widget</code> can be anything that can have <code>WidgetName()</code> called on it.</p> <p>Because you declared a <code>WidgetName()</code> for <code>*Button</code> and not for <code>Button</code>, that means that a <code>*Button</code> is a <code>Widget</code>, and a <code>Button</code> is not a <code>Widget</code>.</p> <p>The literal <code>Button{ ... }</code> is a <code>Button</code>, while <code>&amp;Button{ ... }</code> is a <code>*Button</code> (a pointer to an anonymous <code>Button</code>). Therefore the second one is a <code>Widget</code>, and can be placed into the map, and the first one isn&#39;t.</p></pre>ZenSwordArts: <pre><p>You could also remove the pointer from the method receiver like:</p> <pre><code>func (b Button) WidgetName() string { return b.Name } </code></pre> <p>Maybe <a href="http://nathanleclaire.com/blog/2014/08/09/dont-get-bitten-by-pointer-vs-non-pointer-method-receivers-in-golang/" rel="nofollow">this little tutorial</a> can help you?</p></pre>twek: <pre><p>Thanks but (while not shown in this case) the interface method I am messing with mutates the structure, so I have todo what <a href="/u/TicklyBaby" rel="nofollow">/u/TicklyBaby</a> suggested, however now m[0] is a *widget.Button, how do I de-reference it?</p></pre>gohacker: <pre><p>Dot operator automatically dereferences pointers. Read <a href="https://golang.org/ref/spec">https://golang.org/ref/spec</a>, it is short.</p></pre>twek: <pre><p>I guess its not so much dereferencing...</p> <p>I guess my question is why does Func1 work but Func2 not?</p> <p><a href="https://play.golang.org/p/D953fWdBY-" rel="nofollow">https://play.golang.org/p/D953fWdBY-</a></p></pre>PsyWolf: <pre><p>Because you&#39;re passing a person <strong>value</strong> into the execute function so it can only access the function on the value. If you pass a person <strong>pointer</strong> into the execute function by changing line #25 to </p> <pre><code>tmpl.Execute(os.Stdout, &amp;Person{Name:&#34;Bob&#34;}) </code></pre> <p>by adding the <strong>&amp;</strong> before the person struct literal, then both Func1 and Func2 will work as expected.</p></pre>ZenSwordArts: <pre><p>It&#39;s kinda hard for me to understand what you are trying to achieve. If you know the type(Button in this case) you can dereference by type assertion like this:</p> <pre><code>fmt.Println(*w.(*Button)) </code></pre></pre>twek: <pre><p>Can you do</p> <pre><code>fmt.Println(*w.(*Widget)) </code></pre> <p>Type assert to an interface?</p></pre>twek: <pre><p>Here is an example of what I was trying to achieve (kinda...)</p> <p>Why does Func1 work but not Func2? <a href="https://play.golang.org/p/D953fWdBY-" rel="nofollow">https://play.golang.org/p/D953fWdBY-</a></p></pre>lothamer: <pre><p>Func2 requires Person to be a pointer. If you change Person like so <a href="https://play.golang.org/p/WmmLYZTlTQ" rel="nofollow">https://play.golang.org/p/WmmLYZTlTQ</a>, both functions return a value.</p></pre>twek: <pre><p>So since Func2 requires a Person Pointer, you pass in a Person Pointer to execute, and when execute accesses things like Data it auto-dereferences?</p></pre>lothamer: <pre><p>Yeah, I think that&#39;s about right.</p></pre>TicklyBaby: <pre><p>Your function WidgetName takes a pointer to a Button not a Button so you need a pointer to a Button to satisfy the Widget interface. &amp; is the &#34;address of&#34; operator, the same as in C.</p></pre>

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

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