Uniqueness of type switch cases

May 21, 2024

Finally, the last important bit from this paragraph:

Type switches

Cases then match actual types T against the dynamic type of the expression x. As with type assertions, x must be of interface type, but not a type parameter, and each non-interface type T listed in a case must implement the type of x. The types listed in the cases of a type switch must all be different.

Today we’re examining this part:

The types listed in the cases of a type switch must all be different.

This might seem pretty obvious. And it probably is obvious that all of these are invalid, and won’t compile:

switch x.(type) {
case int:
case int:
}

switch x.(type) {
case io.Closer:
case io.Closer:
}

What’s likely less obvious is that you can still get away with logically duplicate types if you try. Or more dangerously, perhaps, if you aren’t paying close attention:

type closer interface{ Close() error }

switch x.(type) {
case io.Closer:
case closer:
}

In this case, io.Closer has exactly the same definition as our local closer type. But because they are different named types, they are both allowed.

What’s more, you can have overlapping interface definitions in a switch statement:

switch x.(type) {
case io.Closer:
case io.ReadCloser:
}

This is very important! In the above type switch, any value for x that implements the Close() method will not trigger the io.ReadCloser case, even if it satisfies the io.ReadCloser interface! In a case like this, you almost certainly want to put the more specific interface first:

switch x.(type) {
case io.ReadCloser:
case io.Closer:
}

And one last note, of something that won’t work, but isn’t always obvious:

switch x.(type) {
case byte:
case uint8:
}

This doesn’t work because byte is an alias of uint8. So as far as the compiler is concerned, these types are identical. (as are rune and int32, interface{} and any, and any derrivitive types of these, such as []byte and []uint8 or chan<- any and chan<- interface{}).

Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Get daily content like this in your inbox!

Subscribe