Type switches

May 16, 2024

Back in December we looked at type assertions, which allow us to assert whether an interface type is of a specific underlying type. In that conversation, I promised we’d get to the more flexible type switches. And now, at long last, we have arrived!

Type switches

A type switch compares types rather than values. It is otherwise similar to an expression switch. It is marked by a special switch expression that has the form of a type assertion using the keyword type rather than an actual type:

switch x.(type) {
// cases
}

When looking at switch statements, we looked at equivalent if-else blocks and switch statements. Let’s introduce type switches with a similar example comparison, before diving into the details tomorrow. These two code snippets are equivalent:

if _, ok := x.(int) {
	/* ... */
} else if _, ok := x.(float64) {
	/* ... */
} else if _, ok := x.(string) {
	/* ... */
}

and

switch x.(type) {
	case int:
		/* ... */
	case float64:
		/* ... */
	case string:
		/* ... */
}

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 .

Related Content


Type switches conclusion

Two final items with regard to type switches, before we move on to the next topic: Type switches … The type switch guard may be preceded by a simple statement, which executes before the guard is evaluated. This is pretty straight forward. It works just like the simple statements in if statements and normal switch statements. A simple statement can be used both with or without a temporary variable. In other words, both of these are valid:


Type switches with generics

More live coding today! Join me! And bring your questions. Type switches … A type parameter or a generic type may be used as a type in a case. If upon instantiation that type turns out to duplicate another entry in the switch, the first matching case is chosen. func f[P any](x any) int { switch x.(type) { case P: return 0 case string: return 1 case []P: return 2 case []byte: return 3 default: return 4 } } var v1 = f[string]("foo") // v1 == 0 var v2 = f[byte]([]byte{}) // v2 == 2 The example included is nice, because it shows two examples of the type parameter P being used: Both the first case (case P) and third (case []P) use the type parameter.


A long type switch example

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:

Get daily content like this in your inbox!

Subscribe