In Go, how do we identify the type of an object? To get the type of an object in Python, simply use typeof
function. Is it possible to implement the same thing in Go? Yes, of course, in this article, I will show you 3 ways of getting the object's type in Go.
Use string formatting to get the object's type
Package fmt implements formatted I/O with functions analogous to C's printf
and scanf
. The format 'verbs' are derived from C's but are simpler. With the verb 'T', we can easily get the object's type at the runtime:
%T a Go-syntax representation of the type of the value
In example below, I will use Printf()
function to print out the type of object:
package main
import (
"fmt"
)
func main() {
// create an interface contains multiple types of data
types := []interface{}{"a", 6, 6.3, true, []int{4, 3, 4, 1}, map[string]int{
"Harry Potter": 23,
"Mary Jane": 19,
}}
for _, v := range types {
// for each variable, print out the type
fmt.Printf("Type of %v is %T", v, v)
fmt.Println()
}
}
Output:
Type of a is string
Type of 6 is int
Type of 6.3 is float64
Type of true is bool
Type of [4 3 4 1] is []int
Type of map[Harry Potter:23 Mary Jane:19] is map[string]int
With this function, we can print the struct type. Consider the example below:
package main
import "fmt"
func main() {
// create a person
p := person{"Ariana", 25}
fmt.Printf("Type of %v is %T", p, p)
}
type person struct {
fullName string
age int
}
Output:
Type of {Ariana 25} is main.person
Using string reflect package to return the object's type
Package reflect implements run-time reflection, allowing a program to manipulate objects with arbitrary types. The typical use is to take a value with static type interface{} and extract its dynamic type information by calling TypeOf, which returns a Type.
A call to ValueOf returns a Value representing the run-time data. Zero takes a Type and returns a Value representing a zero value for that type.
This example shows how to use reflect
package to return the object's type at run time
package main
import (
"fmt"
"reflect"
)
func main() {
// create a person
p := person{"Ariana", 25}
// get the object's type
typeOfPerson := reflect.TypeOf(p).String()
fmt.Println("Type of", p, "is", typeOfPerson)
types := []interface{}{"a", 6, 6.3, true, []int{4, 3, 4, 1}, map[string]int{
"Harry Potter": 23,
"Mary Jane": 19,
}}
for _, v := range types {
// for each variable, print out the type
fmt.Println("Type of", v, "is", reflect.TypeOf(v).String())
}
}
type person struct {
fullName string
age int
}
Output:
Type of {Ariana 25} is main.person
Type of a is string
Type of 6 is int
Type of 6.3 is float64
Type of true is bool
Type of [4 3 4 1] is []int
Type of map[Harry Potter:23 Mary Jane:19] is map[string]int
Using type assertions to check the type of object
If
T
 is not an interface type,Âx.(T)
 asserts that the dynamic type ofÂx
 is identical to the typeÂT
. In this case,ÂT
 must implement the (interface) type ofÂx
; otherwise the type assertion is invalid since it is not possible forÂx
 to store a value of typeÂT
. IfÂT
 is an interface type,Âx.(T)
 asserts that the dynamic type ofÂx
 implements the interfaceÂT
.
Here's an example of using type assertions to find out the type of the object.
package main
import "fmt"
func main() {
// create an interface contains multiple types of data
types := []interface{}{"a", 6, 6.3, true, []int{4, 3, 4, 1}, map[string]int{"Harry Potter": 23, "Mary Jane": 19}}
for _, v := range types {
// for each variable, print out the type
fmt.Println("Type of", v, "is", typeof(v))
}
}
// function find out the object's type
func typeof(v interface{}) string {
switch v.(type) {
case int:
return "int"
case float64:
return "float64"
case string:
return "string"
default:
return "unknown"
}
}
Output:
Type of a is string
Type of 6 is int
Type of 6.3 is float64
Type of true is unknown
Type of [4 3 4 1] is unknown
Type of map[Harry Potter:23 Mary Jane:19] is unknown
Summary
In this article, I have introduced three methods to return a object's type at runtime: using string formatting, go reflect package and type assertions. Every method has a different best use case:
- string formatting - simple and lightweight (not necessary to import reflect package)
- reflect package - we have access to the full reflection capabilities when we need more information about the type.
- type assertions - allows for type grouping, such as all
int32
,int64
,uint32
,uint64
types as "int". Noted that, we do not find out a specific object's type but useswitch
statement, so if we don't list all data types to compare, there won't be a matching case.
References
https://pkg.go.dev/fmt
https://pkg.go.dev/reflect
http://golang.org/ref/spec#Type_assertions
Further Reading
How to find the type of an object in Go?