UP | HOME

Go: Type Assertions

Table of Contents

1 Type switch

A switch can also be used to discover the dynamic type of an interface variable. Such a type switch uses the syntax of a type assertion with the keyword type inside the parentheses. If the switch declares a variable in the expression, the variable will have the corresponding type in each clause. It's also idiomatic to reuse the name in such cases, in effect declaring a new variable with the same name but a different type in each case.

var t interface{}
t = functionOfSomeType()

switch t := t.(type) {
default:
        fmt.Printf("unexpected type %T\n", t) // %T prints whatever type t has
case bool:
        fmt.Printf("boolean %t\n", t) // t has type bool
case int:
        fmt.Printf("integer %t\n", t) // t has type int
case *bool:
        fmt.Printf("pointer to boolean %t\n", t) // t has type *bool
case *int:
        fmt.Printf("pointer to integer %t\n", t) // t has type *intt
}

Type switches are a form of interface conversion: they take and interface and, for each case in the switch, in a sense convert it to the type of that case. The first case finds a concrete value; the second converts the interface into another interface. It's perfectly fine to mix types this way.

type Stringer interface {
        String() string
}

var value interface{} // Value provided by caller.
switch str := value.(type) {
case string:
        return str
case Stringer:
        return str.String()
}

2 Interface conversions and type assertions

What if there's only one type we care about? If we know the value holds a string and we just want to extract it? A one-case type switch would do, but so would a type assertion. A type assertion takes an interface value and extracts from it a value of the specified explicit type. The syntax borrows from the clause opening a type switch, but with an explicit type rather than the type keyword and the result is a new value with the static type typeName. That type must either be the concrete type held by the interface, or a second interface type that the value can be converted to.

value.(typeName)
// To extract the string we know is in the value, we could write:
str := value.(string)

But if it turns out that the value does not contain a string, the program will crash with a run-time error. To guard against that, use the "comma, ok" idiom to test, safely, whether the value is a string. If the type assertion fails, str will still exist and be of type string, but it will have the zero value, an empty string.

str, ok := value.(string)
if ok {
        fmt.Printf("string value is: %q\n", str)
} else {
        fmt.Printf("value is not a string\n")
}

Author: Pavel Vavilin

Created: 2017-10-27 Fri 01:30

Validate