A long type switch example

May 24, 2024

We’ve been looking at type switches since last week. Today the spec shows us a large example, comparing type switches to the equivalent expressed without them.

Type switches

Given an expression x of type interface{}, the following type switch:

switch i := x.(type) {
case nil:
	printString("x is nil")                // type of i is type of x (interface{})
case int:
	printInt(i)                            // type of i is int
case float64:
	printFloat64(i)                        // type of i is float64
case func(int) float64:
	printFunction(i)                       // type of i is func(int) float64
case bool, string:
	printString("type is bool or string")  // type of i is type of x (interface{})
default:
	printString("don't know the type")     // type of i is type of x (interface{})
}

could be rewritten:

v := x  // x is evaluated exactly once
if v == nil {
	i := v                                 // type of i is type of x (interface{})
	printString("x is nil")
} else if i, isInt := v.(int); isInt {
	printInt(i)                            // type of i is int
} else if i, isFloat64 := v.(float64); isFloat64 {
	printFloat64(i)                        // type of i is float64
} else if i, isFunc := v.(func(int) float64); isFunc {
	printFunction(i)                       // type of i is func(int) float64
} else {
	_, isBool := v.(bool)
	_, isString := v.(string)
	if isBool || isString {
		i := v                         // type of i is type of x (interface{})
		printString("type is bool or string")
	} else {
		i := v                         // type of i is type of x (interface{})
		printString("don't know the type")
	}
}

Let’s walk through this example.

v := x  // x is evaluated exactly once

The comment says it all, but it’s important: x.(type) is not evaluated for each case statement; it’s evaluated only once.

if v == nil {
	i := v                                 // type of i is type of x (interface{})
	printString("x is nil")
} else …

This code wont’ actually compile. It’s creating a variable (i) that isn’t used. But for illustration purposes, it’s valid, and demonstrates that within the case nil block, i’s type and value are both the same as that of x, or interface{}.

… else if i, isInt := v.(int); isInt {
	printInt(i)                            // type of i is int
} else if i, isFunc := v.(func(int) float64); isFunc {
	printFunction(i)                       // type of i is func(int) float64
} else …

In both of these cases, i has a type distinct from x—it’s type is int or float64, respectively, depending on which, if either, of the type assertions evaluates to true.

… else {
	_, isBool := v.(bool)
	_, isString := v.(string)
	if isBool || isString {
		i := v                         // type of i is type of x (interface{})
		printString("type is bool or string")
	} else {
		i := v                         // type of i is type of x (interface{})
		printString("don't know the type")
	}
}

This code snippet handles both case bool, string and default. Let’s look at these individually:

	_, isBool := v.(bool)
	_, isString := v.(string)
	if isBool || isString {
		i := v                         // type of i is type of x (interface{})
		printString("type is bool or string")
	} else …

This case demonstrates the behavior of a type switch case with multiple types: case bool, string. The important thing to notice is that i’s type and value are, once again, identical to that of x. This means we cannot use i in any way that depends on its specific value. For example, it could not be passed to printString direction as printString(i) (assuming a function signature of printString(string)).

	… {
		i := v                         // type of i is type of x (interface{})
		printString("don't know the type")
	}
}

And finally, the equivalent of the default case. Once again, i is identical to x.

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