Interfaces · 3 MIN READ

Asking an interface what it is holding

Read a value out of an interface without risking a panic.

A type assertion has two forms and the difference matters. v := x.(int) panics when x is not an int. v, ok := x.(int) never panics: ok says whether it worked, and v is the zero value when it did not. In anything that handles input you did not write, the two-value form is the only one.

A type switch is the same question asked about several types at once, and it is how Go writes what other languages do with pattern matching or a visitor.

SEE THE IDEA

Inspect a dynamic type once at the boundary

  1. 01

    Input

    go
    value any

    The dynamic type is not yet known

  2. 02

    Dispatch

    go
    switch v := value.(type)

    Choose a concrete type case

  3. 03

    Typed branch

    go
    case string:

    v has the selected type

A type switch can handle nil, known types and a default case.

In practice

Use a type switch when an API intentionally accepts several unrelated kinds of values. Put the type-dependent behavior in a small boundary function, then pass concrete values into the rest of your code. A case listing multiple types leaves the case variable with the original interface type.

Watch out

A type switch sees the exact dynamic type. A named string type is not the same case as string unless you handle it explicitly.

Official reference ↗

Work through the exercise

go
package main

import "fmt"

// Describe returns "int 7", "string go", "bool true" or
// "unknown" for anything else. Use a type switch.
func Describe(value any) string {
	return ""
}

func main() { fmt.Println(Describe(7)) }
Try it yourself

Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.

Progress stays in this browser. No account needed.