Reflection in Practice
Overview
The reflect package provides runtime type inspection. Use sparingly—prefer generics or interfaces when possible.
Type and Value
import "reflect"
x := 42
t := reflect.TypeOf(x) // Type information
v := reflect.ValueOf(x) // Value information
fmt.Println(t.Name()) // int
fmt.Println(t.Kind()) // int
fmt.Println(v.Int()) // 42Inspecting Structs
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
u := User{Name: "Alice", Email: "a@b.com"}
t := reflect.TypeOf(u)
v := reflect.ValueOf(u)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
tag := field.Tag.Get("json")
fmt.Printf("%s: %v (tag: %s)\n", field.Name, value, tag)
}Modifying Values
x := 42
v := reflect.ValueOf(&x).Elem() // Need pointer for modification
v.SetInt(100)
fmt.Println(x) // 100Calling Methods
type Calculator struct{}
func (c Calculator) Add(a, b int) int { return a + b }
c := Calculator{}
v := reflect.ValueOf(c)
method := v.MethodByName("Add")
args := []reflect.Value{reflect.ValueOf(2), reflect.ValueOf(3)}
result := method.Call(args)
fmt.Println(result[0].Int()) // 5When to Use
✅ Appropriate: - Serialization/deserialization - ORM mapping - Dependency injection - Test utilities
❌ Avoid: - Performance-critical paths - Simple type conversions - When generics suffice
Summary
| Function | Purpose |
|---|---|
TypeOf() |
Get type info |
ValueOf() |
Get value wrapper |
Kind() |
Base type category |
Field() |
Access struct field |
MethodByName() |
Access method |