The advantage is that it allows interfaces to evolve without having to muck around with setting up shared dependencies. In a language like Java, if library A and library B want to share an interface, you have to create library C for the interface and modify A and B to depend on it, and if you want to add a method you have to modify all three at the same time. Furthermore, changing an interface isn't backward compatible so the correct way is to create a new interface every time you make a change.
In Go, they can both declare the same interface or even skip formally declaring it and just agree to implement the same methods. Furthermore, if one of them decides to implement a new method, the other can just copy the method signature and they stay compatible. This makes it a lot easier to coordinate API changes.
> 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.
In Go, they can both declare the same interface or even skip formally declaring it and just agree to implement the same methods. Furthermore, if one of them decides to implement a new method, the other can just copy the method signature and they stay compatible. This makes it a lot easier to coordinate API changes.