> What do you call it when you assign a value of one type to a variable of another type and the language creates a new value, different from the one you were assigning, and stores that new value in the variable? In C++ this is called "implicit conversion."
Right, I addressed this when I said:
> unless you consider "assigning a concrete value to an interface" to be an "implicit conversion", but Java does this too
So let's just skip to your reply to that bit:
> I guess, but this is much less of a conversion than Go is performing because the runtime value does not change at all. It's the same pointer, not a tuple containing the pointer. Unlike in Go, this assignment may very often be correctly implemented by a sequence of 0 instructions!
Yes, Java and Go have different implementations/conceptions of "interface". I don't see what bearing this has. From the programmer's perspective, Java's interface assignment isn't more explicit than Go's even though the underlying mechanisms differ. In particular, Go needs to create a new "header" value because its interfaces are polymorphic across any type (including primitives and value types!) whereas Java's are polymorphic only across objects and Java attaches a header to every object.
> Importantly, the meaning of "foo == null" is unchanged.
Go's `foo == nil` isn't changed either. It behaves like it does for all reference types. The difference between Java and Go is conceptual, but the `==` operator is coherent within each of them.
> This is not because Java performs implicit conversions of interface types to specific pointer types at the null check.
Agreed, and to be clear, I didn't claim it did. Nor does Go, so I'm not quite sure what you're responding to here.
> It's because in Java interfaces are unable to express having a concrete value of a specific class which is null, because they are just pointers.
> One might say "Java interfaces do not have inner and outer nil values" as a shorthand for this.
Right, but we were debating whether or not Go interfaces have inner or outer nils. Consider `var x interface{} = 0`. What's the outer value? And what's the inner value? The whole point of my comment is that you're conceiving of Go interfaces as having inner and outer values, but Go interfaces are just a fat pointer. As such, you can have pointers to pointers with Go interfaces. And while you can't have pointers to pointers with Java interfaces, you can elsewhere in Java so a Java programmer should be able to reason about Go interfaces because they can understand the concept of a nullable pointer to a nullable pointer.
Ultimately, it seems that you're criticizing Go for having a different interface mechanism than Java, and you get bugs when you treat Go interfaces like Java interfaces. And Go made the right choice here, because it can express polymorphism over a wider range of types than just objects (contra Java interfaces) and indeed it doesn't have any sort of object/primitive bifurcation--from the perspective of Go interfaces, all concrete types are just data.