Go reflect:运行时反射与自省
探索reflect包,实现在运行时检查类型、调用方法和修改结构体字段。 · 难度:入门 · +15XP
reflect包核心概念
reflect包允许程序在运行时检视自身类型和值。两个核心类型:reflect.Type(表示类型信息)和reflect.Value(表示值)。通过reflect.TypeOf()和reflect.ValueOf()获取。
| 函数/方法 | 用途 |
|---|---|
| reflect.TypeOf(i) | 返回接口的动态类型 |
| reflect.ValueOf(i) | 返回接口的动态值 |
| v.Kind() | 返回底层类型(如struct, slice, ptr) |
| v.Field(i) | 获取结构体的第i个字段 |
| v.Method(i).Call() | 调用第i个方法 |
可设置性(Settability)
通过反射修改值必须使用指针,且调用v.Elem()获取可设置的值。例如:reflect.ValueOf(&x).Elem().SetInt(42)。
代码示例:打印结构体字段与方法
package main
import (
"fmt"
"reflect"
)
type Person struct {
Name string
Age int
}
func (p Person) Greet() string {
return fmt.Sprintf("Hi, I'm %s, age %d", p.Name, p.Age)
}
func main() {
p := Person{Name: "Alice", Age: 30}
v := reflect.ValueOf(p)
t := v.Type()
fmt.Println("Fields:")
for i := 0; i < v.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
fmt.Printf(" %s (%s) = %v
", field.Name, field.Type, value.Interface())
}
fmt.Println("Methods:")
for i := 0; i < v.NumMethod(); i++ {
method := t.Method(i)
fmt.Printf(" %s
", method.Name)
}
// 调用方法
result := v.MethodByName("Greet").Call(nil)
fmt.Println("Greeting:", result[0].String())
}
练习提示
写一个通用函数SetField(obj interface{}, name string, value interface{}),通过反射设置结构体字段的值。注意处理指针和类型匹配。