<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't the best use case but it illustrates my point. I hope...</p>
<hr/>**评论:**<br/><br/>TicklyBaby: <pre><p>Add <code>&</code> before Button on line 21:</p>
<blockquote>
<p>m[0] = &Button{Name: "Jim"}</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'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>&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'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'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, &Person{Name:"Bob"})
</code></pre>
<p>by adding the <strong>&</strong> before the person struct literal, then both Func1 and Func2 will work as expected.</p></pre>ZenSwordArts: <pre><p>It'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'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. & is the "address of" operator, the same as in C.</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传