Go Reflection Cheat Sheet
Using reflect.Type and reflect.Value to inspect and mutate values at runtime, plus struct tag parsing for encoders and ORMs.
Type and Value
reflect.TypeOf and reflect.ValueOf are the two entry points into the reflection API.
import "reflect"x := 42t := reflect.TypeOf(x) // reflect.Type: intv := reflect.ValueOf(x) // reflect.Value wrapping 42fmt.Println(t.Kind()) // reflect.Intfmt.Println(t.Name()) // "int"fmt.Println(v.Int()) // 42 (typed accessor, panics if Kind != Int)// Kind is the underlying category (Struct, Slice, Ptr, Int, ...)// Type can differ from Kind for named types, e.g. type MyInt int has Kind() == Int
Inspecting Struct Fields
Iterate fields, read tags, and get/set values via reflection.
type User struct { Name string `json:"name" validate:"required"` Age int `json:"age"`}u := User{Name: "Alice", Age: 30}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 (%s) = %v, json tag=%q\n", field.Name, field.Type, value, tag)}
Mutating Values (Requires a Pointer)
You can only Set through an addressable, settable Value — pass a pointer and call Elem().
func setName(u *User, name string) { v := reflect.ValueOf(u).Elem() // dereference the pointer to get settable Value field := v.FieldByName("Name") if field.IsValid() && field.CanSet() { field.SetString(name) }}u := &User{Name: "Bob"}setName(u, "Robert")fmt.Println(u.Name) // "Robert"// reflect.ValueOf(someNonPointer).Elem() panics -- Elem() needs a Ptr or Interface Kind
Calling Functions Dynamically
reflect.Value.Call invokes a function found via reflection, e.g. for plugin systems.
func add(a, b int) int { return a + b }fn := reflect.ValueOf(add)args := []reflect.Value{reflect.ValueOf(3), reflect.ValueOf(4)}result := fn.Call(args) // []reflect.Valuefmt.Println(result[0].Int()) // 7// Checking a value implements an interfacevar w io.Writert := reflect.TypeOf(os.Stdout)fmt.Println(t.Implements(reflect.TypeOf(&w).Elem()))
Key reflect Concepts
Terminology that trips people up when starting with reflection.
- reflect.Type- static type description: name, kind, methods, fields
- reflect.Value- a boxed runtime value you can inspect/set/call
- Kind()- the underlying category (Struct, Slice, Map, Ptr, Int, Func...)
- Elem()- dereferences a Ptr/Interface Value or gets element type of Slice/Array/Map
- CanSet()- true only for values obtained via an addressable pointer's Elem()
- StructTag- raw tag string on a field, parsed with .Get("key")
Reach for reflection only at the edges of your program (encoders, ORMs, dependency injection, generic-ish utilities before generics existed) — it bypasses compile-time type checking and is noticeably slower than direct code, so keep it out of hot paths and prefer Go generics where they now suffice.