Reflection
Use reflection sparingly at framework or boundary layers; prefer ordinary static Go code when you can.
Canonical guidance
- prefer static code first
- use reflection when the program truly must inspect unknown types at runtime
- keep reflective code narrow and well-tested
Use when
- generic serialization or decoding layers
- framework hooks
- struct-tag-driven behavior
Avoid
- reflection in ordinary request logic
- reflective mutation without kind checks
- hiding type errors until runtime without strong reason
Preferred pattern
func fieldNames(v any) []string {
t := reflect.TypeOf(v)
if t.Kind() == reflect.Pointer {
t = t.Elem()
}
var names []string
for i := 0; i < t.NumField(); i++ {
names = append(names, t.Field(i).Name)
}
return names
}
Anti-pattern
- replacing straightforward concrete code with reflection for no measurable gain
Explanation: This anti-pattern is tempting because it feels generic, but it usually trades compile-time clarity for runtime fragility.
Why
- reflection is powerful but expensive in readability and safety margin
Related pages
Sources
- reflect package - Go Team
- The Go Programming Language Specification - Go Team