Go's reflection is a powerful feature that allows inspection and manipulation of program types at runtime. It's primarily implemented through the reflect
package.
Why Use Reflection?
- Dynamic Type Checking: Examine variable types and properties at runtime
- Dynamic Invocation: Call functions or methods of unknown types at runtime
- Serialization/Deserialization: Traverse struct fields for JSON parsing
- Frameworks & Libraries: Handle dynamic types in DI and ORM frameworks
Core Concepts
-
Type: Represents Go types using
reflect.Type
-
Value: Represents Go values using
reflect.Value
Basic Operations
1. Getting Reflection Objects
- Use
reflect.TypeOf
for type information - Use
reflect.ValueOf
for value information
2. Type Checking
- Use the
Kind
method to check variable categories
3. Struct Field Operations
- Get and set struct field values, invoke struct methods
Code Examples
Getting Type and Value
package main
import (
"fmt"
"reflect"
)
func main() {
var x float64 = 3.4
fmt.Println("type:", reflect.TypeOf(x))
fmt.Println("value:", reflect.ValueOf(x))
}
Dynamic Value Setting
package main
import (
"fmt"
"reflect"
)
func main() {
var x float64 = 3.4
v := reflect.ValueOf(&x)
v = v.Elem()
if v.CanSet() {
v.SetFloat(7.1)
}
fmt.Println(x)
}
Working with Struct Fields
package main
import (
"fmt"
"reflect"
)
type Person struct {
Name string
Age int
}
func main() {
p := Person{"Alice", 30}
v := reflect.ValueOf(&p).Elem()
name := v.FieldByName("Name")
age := v.FieldByName("Age")
fmt.Println("Name:", name)
fmt.Println("Age:", age)
if name.CanSet() {
name.SetString("Bob")
}
if age.CanSet() {
age.SetInt(40)
}
fmt.Println("Updated person:", p)
}
Important Considerations
- Performance: Reflection adds overhead; use cautiously in performance-critical code
- Type Safety: Bypasses compile-time type checking, may cause runtime errors
- Exported Fields: Only exported fields (capitalized) can be accessed
Common Use Cases
- Serialization/Deserialization: JSON, XML parsing
- Dependency Injection: Automatic dependency wiring
- ORM Frameworks: Object-relational mapping
Summary
Reflection is a powerful Go feature for runtime type and value manipulation. While it offers great flexibility, consider performance implications and type safety. Use it judiciously based on your specific requirements.