Reflection is the ability of a program to inspect the types and values of variables at runtime. This can be interesting for generating generic code in the same way that happens when we use interfaces , although I honestly believe its greatest utility is for debugging potential code issues.
If you are new to the world of Go, I recommend the following previous articles:
- Go basics
- Go functions
- Go unit tests
- Go pointers
- Go interfaces
- Go structs
- Go generics
- Go errors
- Go routines
- Go strings, chars, and runes
- Go defer
- Go first class functions
Reflection package:
The reflection package offers several interesting methods that allow us to analyze the types and values of our variables data. The best way to see this is through an example.
package main
import (
"fmt"
"reflect"
)
type order struct {
ordId int
customerId int
}
type employee struct {
name string
id int
address string
salary int
country string
}
func main() {
o := order{
ordId: 456,
customerId: 56,
}
e := employee{
name: "Naveen",
id: 565,
address: "Coimbatore",
salary: 90000,
country: "India",
}
fmt.Println("o ValueOf.Kind: ", reflect.ValueOf(o).Kind())
fmt.Println("o TypeOf.Kind: ", reflect.TypeOf(o).Kind())
fmt.Println("o TypeOf.Name: ", reflect.TypeOf(o).Name())
fmt.Println("o ValueOf.NumField: ", reflect.ValueOf(o).NumField())
for i := 0; i < reflect.ValueOf(o).NumField(); i++ {
switch reflect.ValueOf(o).Field(i).Kind() {
case reflect.Int:
fmt.Printf("%v -> Int: %d\n", reflect.TypeOf(o).Field(i).Name, reflect.ValueOf(o).Field(i).Int())
case reflect.String:
fmt.Printf("%v -> String: %s\n", reflect.TypeOf(o).Field(i).Name, reflect.ValueOf(o).Field(i).String())
default:
fmt.Println("Unsupported type.")
}
}
fmt.Println("---------")
fmt.Println("e ValueOf.Kind: ", reflect.ValueOf(e).Kind())
fmt.Println("e TypeOf.Kind: ", reflect.TypeOf(e).Kind())
fmt.Println("e TypeOf.Name: ", reflect.TypeOf(e).Name())
fmt.Println("e ValueOf.NumField: ", reflect.ValueOf(e).NumField())
for i := 0; i < reflect.ValueOf(e).NumField(); i++ {
switch reflect.ValueOf(e).Field(i).Kind() {
case reflect.Int:
fmt.Printf("%v -> Int: %d\n", reflect.TypeOf(e).Field(i).Name, reflect.ValueOf(e).Field(i).Int())
case reflect.String:
fmt.Printf("%v -> String: %s\n", reflect.TypeOf(e).Field(i).Name, reflect.ValueOf(e).Field(i).String())
default:
fmt.Println("Unsupported type.")
}
}
}
o ValueOf.Kind: struct
o TypeOf.Kind: struct
o TypeOf.Name: order
o ValueOf.NumField: 2
ordId -> Int: 456
customerId -> Int: 56
---------
e ValueOf.Kind: struct
e TypeOf.Kind: struct
e TypeOf.Name: employee
e ValueOf.NumField: 5
name -> String: Naveen
id -> Int: 565
address -> String: Coimbatore
salary -> Int: 90000
country -> String: India