Go's Named Types aren't Types

I always thought that the “types” that are created using Go’s type keyword were, in some vague sense, new, unique, original; but in any case separate and distinct types. It turns out, this is a misunderstanding.

The “types” created using the type declaration are not somehow newly “created”. Instead, the type keyword merely introduces a new name for an existing type. Which is why every newly declared type has an “underlying type”.

This is obvious for type Name string, but even a struct is an existing type (namely, that struct type), and saying type Thing struct { ... } merely introduces a new name for a struct with the specified layout.

Because each named type has an underlying type, it is possible to convert between types that share the same underlying type; a fact that is being used frequently in idiomatic Go.

In a way, Go’s type is less like the class declaration in Python, Java, or C++, and more like a typedef — but an enforced typedef (whereas the classic typedef in C is merely optical, but not enforced by the compiler).