Type assertion and type switch

If we have a value and want to convert it to another or a specific type (in case of interface{}), we can use type assertion. A type assertion takes a value and tries to create another version in the specified explicit type.

This is how we can use type assertion:

x.(T)

x is the variable whose type must be interface, and T is the type which you want to check. For example:

package main

import "fmt"

func printValue(v interface{}) {
  fmt.Printf("The value of v is: %v", v.(int))
}

func main() {
  v := 10
  printValue(v)
}

The running result is:

  The value of v is: 10

In the above example, using v.(int) to assert the v is int variable.

if the type assertion operation fails, a running panic will occur: change

fmt.Printf("The value of v is: %v", v.(int))  

into:

fmt.Printf("The value of v is: %v", v.(string))

Then executing the program will get following error:

  panic: interface conversion: interface is int, not string
  
  goroutine 1 [running]:
  panic(0x4f0840, 0xc0820042c0)
  ......

To avoid this, type assertion actually returns an additional boolean variable to tell whether this operations holds or not. So modify the program as follows:

package main

import "fmt"

func printValue(v interface{}) {
  if v, ok := v.(string); ok {
    fmt.Printf("The value of v is: %v", v)
  } else {
    fmt.Println("Oops, it is not a string!")
  }

}

func main() {
  v := 10
  printValue(v)
}

This time, the output is:

  Oops, it is not a string!

Type switch

Furthermore, you can also use type switch which makes use of type assertion to determine the type of variable, and do the operations accordingly. Check the following example:

package main

import "fmt"

func printValue(v interface{}) {
  switch v := v.(type) {
  case string:
    fmt.Printf("%v is a string\n", v)
  case int:
    fmt.Printf("%v is an int\n", v)
  default:
    fmt.Printf("The type of v is unknown\n")
  }
}

func main() {
  v := 10
  printValue(v)
}

The running result is here:

  10 is an int

Compared to type assertion, type switch uses keyword type instead of the specified variable type (such as int) in the parentheses.

Checking the errors

Another example is when checking if an error is of a certain type:

if err != nil {
  if msqlerr, ok := err.(*mysql.MySQLError); ok && msqlerr.Number == 1062 {
    log.Println("We got a MySQL duplicate :(")
  } else {
    return err
  }
}

References:
Effective Go;
Go – x.(T) Type Assertions;
How to find a type of a object in Golang?. https://github.com/NanXiao/golang-101-hacks http://www.golangbootcamp.com/book/types#sec-type-conversion


See also