Explain type assertions vs. type switches.

4 minintermediategotype-assertionstype-switchinterfaces

Quick Answer

A type assertion, v, ok := x.(T), checks whether an interface value x holds a concrete type T (or satisfies interface T), returning the value and a boolean success flag in the safe two-value form, or just the value (and a panic on failure) in the single-value form v := x.(T). A type switch, switch v := x.(type) { case int: ...; case string: ... }, checks against multiple possible types in one construct, which is the idiomatic choice whenever you need to branch on more than one possible concrete type. Always prefer the two-value assertion form (v, ok := ...) over the panicking single-value form unless you're certain of the type, since an unexpected type reaching a single-value assertion crashes the program.

Detailed Answer

Both let you recover a concrete type from an interface value, but they fit different shapes of problem.

Single type assertion

var i interface{} = "hello"

s, ok := i.(string)
fmt.Println(s, ok)   // "hello", true

n, ok := i.(int)
fmt.Println(n, ok)   // 0, false — no panic, since we used the two-value form
s := i.(string)   // "hello" — fine here
n := i.(int)       // panic: interface conversion: interface {} is string, not int

The single-value form is only safe when you're certain of the underlying type. Otherwise, always use the two-value form.

Type switch for multiple possibilities

func describe(i interface{}) string {
    switch v := i.(type) {
    case int:
        return fmt.Sprintf("int: %d", v)
    case string:
        return fmt.Sprintf("string: %q", v)
    case bool:
        return fmt.Sprintf("bool: %t", v)
    case nil:
        return "nil value"
    default:
        return fmt.Sprintf("unknown type: %T", v)
    }
}

Inside each case, v is automatically narrowed to that specific type, so v.something type-checks against the concrete type in that branch, not the original interface type.

When to use which

Use a single type assertion when you expect exactly one specific type and want to confirm it. Use a type switch when a value could reasonably be one of several types, and you need different behavior per type. A generic describe or render function over a small, known set of inputs is a typical case.

Related Resources