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