Yet another confused gopher about Interfaces

agolangf · · 469 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I don&#39;t understand interfaces. Being defined as a group of methods, I can&#39;t see the use of writing extra code to group methods that I could just write on my structs without grouping them in an interface. The other confusing part is that they are implemented implicitly <a href="https://tour.golang.org/methods/10" rel="nofollow">https://tour.golang.org/methods/10</a>, how does that help anyone ? I feel like the best part about go is its &#34;no-magic&#34; approach, this seems like a lot of magic to me.</p> <hr/>**评论:**<br/><br/>Sythe2o0: <pre><p>Imagine you have a system where you pass around several different structs that all are supposed to do a similar job. If you write an interface defining the methods that defines that job, you can use the interface type in your functions which use those structs instead of having strict struct types there. So instead of having to write different code to print every single element in your system for example, you can instead write a function which takes in a &#34;Printable&#34; interface which requires the &#34;Print&#34; method for each element. </p> <p>This example is actually very close to a real use case-- in go&#39;s fmt package there is a &#34;Stringer&#34; interface which requires that elements define the &#34;String() string&#34; function to be a part of. Then, if you ever fmt.Println(myStruct), it&#39;ll use your struct&#39;s specific String function in the log. </p></pre>TheMerovius: <pre><p>I think to understand the usefulness of interfaces, looking at the io package is the most insightful. Basically every go code that needs to receive or pass binary data will use an <code>io.Reader</code> and every go code that wants to write out something will use an <code>io.Writer</code>. With that, the user of that code can decide whether they want to read or write the stuff from a file, a buffer, a network connection… You don&#39;t use the interface to just group together methods; you use it to specify &#34;I can use any thing that can do this&#34;.</p> <p>The usefulness of structural instead of nominal typing (that is, to implement interfaces implicitly) is, that it allows to define interfaces for third-party packages. For example, say you want to log stuff in your package, but give your user control over where to and how to do that. You <em>could</em> take a <code>*log.Logger</code>, but that would severely limit what they can do; you can not have a nop <code>*log.Logger</code> (it will always at least format your logging statement, even if you discard it then, and formatting takes time, which is important for verbose logs). You could instead write an interface that has the relevant methods of a <code>*log.Logger</code> and take that. Then your users can write their own nop-logger, which actually does nothing, unless debugging is enabled. Or just pass a <code>*log.Logger</code>. Without the flexibility of structural typing, you couldn&#39;t do that. You&#39;d need to rely on the author of the <code>log</code>-package to write that interface and specify that a <code>*log.Logger</code> implements it. </p> <p>There are other benefits too: Breaking dependency cycles, for example and that it encourages writing small, self-contained interfaces, instead of big ones (like in java).</p></pre>justinisrael: <pre><blockquote> <p>I can&#39;t see the use of writing extra code to group methods that I could just write on my structs without grouping them in an interface. </p> </blockquote> <p>What extra code do you write, aside from a tiny interface definition? The beauty of Go is that interfaces are satisfied implicitly. </p> <p>Take for example the io.Writer. This is one of the most useful interfaces in Go. It means you don&#39;t have to accept a concrete *os.File. You just take anything that has a proper Write() method. Why do you care if it&#39;s a File or socket or buffer? You can make code more flexible and reusable when coding against interfaces. If something can Write() then it&#39;s all you need. </p></pre>justinisrael: <pre><p>Furthermore, when talking about creating your own new interfaces, if you have methods or functions in your library that take a concrete type, then it means users of your library can only pass values of that predefined type. But if you take an interface, then it means users of your library can create their own types, as long as they implement the required interface, they can do whatever else they want. </p></pre>tscs37: <pre><p>Well, the obvious elephant in the room is &#34;what do if there is interface overlap?&#34; and the only real answer is; avoid by using very explicit function names and try to seperate code that could overlap interfaces with differing functionality.</p> <p>At their core, interfaces aren&#39;t really much magic, they&#39;re descriptions of capability.</p> <p>Some interface like io.Writer simply states that all structures that are capable of writing data can be used as it&#39;s type instead. This means underlying code only needs to handle the io.Writer interface and can then handle all other structs or types that are capable of writing as per interface definition.</p> <p>Secondly, the implicit approach solves a bunch of problems; you don&#39;t need to declare something to be part of an interface on top of writing the methods for it. Writing the methods of an interface is sufficient to fulfill an interface according to the compiler.</p> <p>You don&#39;t do much different when it&#39;s explicit except that you now have a buttload of interface relations on some end.</p></pre>vettijoe: <pre><p>Welcome to the first bit of Go, that feels super weird. I had the same question. I was clear on <strong>what</strong> is an interface, just not the <strong>why</strong>! Then I landed here - <a href="http://go-book.appspot.com/interfaces.html" rel="nofollow">http://go-book.appspot.com/interfaces.html</a></p> <p>Follow along the article. I&#39;m sure it&#39;ll leave you with a much better understanding of <em>interfaces</em>. </p></pre>sw0r6f1sh: <pre><p>interfaces are the only way to achieve polymorphisme in Go without resorting to reflection.</p></pre>md2perpe: <pre><p>Interfaces are primarily used as types for arguments to functions and methods to say that all that&#39;s needed by an argument is that it implements a given set of methods.</p></pre>lwcd: <pre><p>Take a look at Dave Cheney&#39;s fantastic talk on SOLID Go Design: <a href="https://www.youtube.com/watch?v=zzAdEt3xZ1M" rel="nofollow">https://www.youtube.com/watch?v=zzAdEt3xZ1M</a></p> <p>(edit)</p> <p>Specifically when he talks about the Liskov Substitution Principle, about 11 mins in.</p></pre>

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

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