Reflection (reflect)
⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 4 min
TL;DR
Go is a strictly typed language. The compiler needs to know what types everything is. However, the reflect package allows you to break this rule. It allows your code to inspect, discover, and even modify the type and value of variables at runtime. It is incredibly powerful, but extremely slow and dangerous.
Mental Model
How It Works
Reflection is heavily used by the standard library.
- When you call
json.Marshal(struct), the JSON library uses reflection to look at your struct, find its fields, read thejson:"name"struct tags, and build the string. - When you use
fmt.Println, it uses reflection to figure out how to format whatever random data you passed into it.
The Two Pillars of Reflection:
reflect.TypeOf(v): Returns the type data (e.g., is it a struct? is it a slice? what are the names of its fields?).reflect.ValueOf(v): Returns the actual data. You can use this to read the values, or (if passed as a pointer) modify the values.
Example
package main
import (
"fmt"
"reflect"
)
type Config struct {
Host string `env:"HOST_IP"`
Port int `env:"HOST_PORT"`
}
func printStructTags(input interface{}) {
// 1. Get the Type of the input
t := reflect.TypeOf(input)
// Ensure the input is actually a struct!
if t.Kind() != reflect.Struct {
fmt.Println("Expected a struct")
return
}
// 2. Iterate over the fields of the struct at runtime
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
// 3. Extract the custom tag string
tag := field.Tag.Get("env")
fmt.Printf("Field: %s, Type: %s, Tag: %s\n", field.Name, field.Type, tag)
}
}
func main() {
c := Config{}
printStructTags(c)
}
Common Interview Questions
Why shouldn’t I use reflect everywhere?
- Performance: Reflection is incredibly slow. It bypasses compiler optimizations and requires dynamic heap allocations.
json.Marshalis actually quite slow compared to code-generated JSON parsers (likeeasyjson) specifically because of reflection. - Safety: If you use reflection to dynamically call a method or extract a field that doesn’t exist, the compiler won’t warn you. Your program will violently
panicat runtime.
What is the difference between Type and Kind?
If you define type MyInt int.
The Type of the variable is MyInt (your custom name).
The Kind of the variable is int (the underlying primitive machine type). Reflection usually cares more about Kind so it knows how to handle the memory.