> Furthermore, changing an interface isn't backward compatible so the correct way is to create a new interface every time you make a change.
That's a feature, not a bug. Say we're using implicit interfaces and have library A that provides an interface Foo and an application B that uses A and passes a Foo to some callback system. Now A gets updated and adds a method to Foo, but existing B binaries still call A with an implementation of the old version of Foo, and things fall apart.
Java's model (and COM's and MS-RPC's) model here is better because it enforces good interface hygiene: incompatible types get incompatible names. Then you can choose whether to support the old name as well as the new name, but you're at least consciously making that choice. D's model worries me because it feels like it's easier to accidentally break things.
You're right that adding a method to an interface is still an incompatible change. If A declares an interface and B uses it as a function parameter, this means that A can change B's API by updating the interface.
One solution is for B to redeclare the same interface (even if it's the same at first). Then when A adds a method, B's interface is unchanged but it's a compatible subset, so nothing breaks.
Also, the specific form of breakage you mention can't happen in Go because Go has no binary shared libraries; all binaries are statically linked and libraries are distributed as source. If there's a compatibility break then a Go developer somewhere will get a compile error. With implicit interfaces you're very likely to be able to fix the problem yourself, without having to coordinate across separate organizations.
The explicit interfaces in Java and especially COM (with its GUID's) were designed to make binary compatibility between shared libraries easy to preserve, so the designers made different tradeoffs.
That's a feature, not a bug. Say we're using implicit interfaces and have library A that provides an interface Foo and an application B that uses A and passes a Foo to some callback system. Now A gets updated and adds a method to Foo, but existing B binaries still call A with an implementation of the old version of Foo, and things fall apart.
Java's model (and COM's and MS-RPC's) model here is better because it enforces good interface hygiene: incompatible types get incompatible names. Then you can choose whether to support the old name as well as the new name, but you're at least consciously making that choice. D's model worries me because it feels like it's easier to accidentally break things.