Here's a container interface. It has a sort() method, which sorts the elements of the container.
Here's a different container interface. It's got a method that tells you what kind of concrete container you have, so you can understand how expensive actions like insert and sort are going to be. But the author was from England, and so called that method "sort".
You can see how that's going to (fail to) work out when you define a "sortable" interface...
Traditional (but even more contrived) examples include "draw" and "fire" doing unexpected things when applied to a gun as opposed to an image or an employee.
First, you really have to split this up into two distinct cases.
The most powerful/useful is when you create an interface in your package for a structure in a different package. It's been years since I've done .NET or Java, but I remember frequently cursing a library developer (often someone at Microsoft or Sun) for exposing a concrete type instead of an interface. In this case, I don't see any downside. Creating a:
type Render interface { Draw() }
And then using my (or someone else's) Gun structure, is no different than using the Gun structure directly and expecting it to render itself to the screen rather than come out of its holster. The interface buys you the level of indirection, but whether you use the interface or the concrete type, it's up to you to know WTF Draw() does.
This first approach is well explained at [1]
In the second case, where a library expects an interface, I agree there's a risk:
// 3rd party package package fastRender
type Drawable interface { Draw() }
func Render(d Drawable) { ... }
// my code: fastRender.Render(new(Gun))
I've lost some degree or type checking. Since my Gun's Draw doesn't explicitly implement fastRender.Drawable, maybe I'm trying to fit a square peg into a round hole. There's nothing the compiler can do to help either.
It sounds a bit like an academic concern to me. Is this something that's actually bitten people in the ass? How is it different than any method that takes primitives? I can pass a []byte of a bitmap to a Music player's Play(data []byte) method...
[1] https://medium.com/@rakyll/interface-pollution-in-go-7d58bcc...
It doesn't seem like a high probability that this would happen on accident, though it might be possible to contrive an example.
I'll have to think about that.
One could possibly force the issue by including an unused function with a deliberately unique name (supports_interface_foo, or maybe a UUID or both) as part of the interface. Can functions added later fill parts of interfaces? If so, this approach would make the situation roughly that of Haskell typeclasses. If not, then this approach makes the situation roughly that of Java interfaces. In either case, it might be appropriate to some pickier interfaces.