Module lessons (2/5)
Type assertion
A type assertion extracts the concrete type from an interface value.
You need it when you have an interface{} (or a "high" interface) in
hand and need to treat it as its specific type to access fields or
methods not present on the interface.
Syntax
var i interface{} = "ciao"
s := i.(string) // "panic" form: panics if it's not a string
s, ok := i.(string) // "comma ok" form: ok = false if it's not a stringTwo forms, two semantics:
| Form | Success | Failure |
|---|---|---|
v := i.(T) | v = value of type T | panic at runtime |
v, ok := i.(T) | v=..., ok=true | v = zero value of T, ok=false |
"Comma ok" form: the safest
var i interface{} = 42
if s, ok := i.(string); ok {
fmt.Println("è stringa:", s)
} else {
fmt.Println("non è stringa, ignoro")
}ok lets you handle the "wrong type" case without a panic. It's the
idiomatic pattern in the vast majority of cases.
Assertion to an interface
The assertion doesn't work only on concrete types, but also on other interfaces:
type Closer interface { Close() error }
func tryClose(x interface{}) {
if c, ok := x.(Closer); ok {
c.Close()
}
}A very common pattern in the standard library: "if my input is also
an io.Closer, call Close at the end".
Assertion on pointers vs values
The assertion must match the dynamic type EXACTLY:
type Cat struct{}
func (c *Cat) Meow() {}
var a interface{} = &Cat{}
c1, ok := a.(*Cat) // ok = true
c2, ok := a.(Cat) // ok = false: it holds *Cat, not Cat*Cat and Cat are distinct types for the type system.
When to use assertion vs type switch
- Only 1 possible type, "feature-detect" check (e.g. cast to an optional interface): type assertion with
comma ok. - 2+ possible types, dispatch over multiple branches: type switch (next lesson).
Try it
Use the comma ok pattern to extract a string from i.
Show hint
Syntax: `v, ok := i.(T)`.
Solution available after 3 attempts
Type assertion to int without comma ok (assume i contains an int).
Show hint
Without `ok` you assume the type is certain; otherwise panic.
Solution available after 3 attempts
What happens with `s := i.(string)` if i contains an int?
var i interface{} = 42
s := i.(string)Recap
v := i.(T): panic if the dynamic type ≠ T.v, ok := i.(T): safe pattern, checkok.- Works also against another interface ("feature detect").
Tand*Tare distinct types for the assertion.- 1 type → assertion; 2+ types → type switch.