Learn Go← Dashboard

Go's duck typing: implicitly satisfied contracts.

Type Assertions & Type Switches

Once you've got an interface value (especially any), you'll sometimes need to recover the concrete type stored inside it.

Type assertion: x.(T)

var i any = "hello"
s := i.(string)            // panics if i isn't a string
s, ok := i.(string)        // safe form: ok=false if mismatch

The two-value form is the safe way. If the assertion fails, ok is false and s is the zero value of T. Without ok, a wrong type panics.

go playground
Loading...

Asserting against an interface

You can assert that a value satisfies another interface — useful for optional behaviour:

type Closer interface { Close() error }

func cleanup(x any) {
    if c, ok := x.(Closer); ok {
        c.Close()
    }
}

This pattern is everywhere in the standard library — for example http.Handler checks if the writer also implements http.Flusher.

Type switch — many assertions at once

When you'd write a chain of if x, ok := v.(T); ok { ... }, use a type switch:

switch v := x.(type) {
case int:    // v is int
case string: // v is string
default:     // v has its original type
}

We already saw a type switch in chapter 4. It's the same syntax — just at a different place in your toolkit.

Given `var i any = 7`, what is the safe way to get the int out?