Go reflect:运行时反射与元编程
掌握reflect包的核心概念Type和Value,学习如何动态检查类型、调用方法和修改字段。 · 难度:入门 · +15XP
反射基础
反射允许程序在运行时检查自身结构,特别是类型信息。Go的reflect包提供两个核心类型:
- reflect.Type:表示Go类型
- reflect.Value:表示运行时的值
获取Type和Value
var x float64 = 3.14
// 获取类型信息
t := reflect.TypeOf(x)
fmt.Println(t.Name()) // float64
fmt.Println(t.Kind()) // float64
// 获取值信息
v := reflect.ValueOf(x)
fmt.Println(v.Float()) // 3.14
fmt.Println(v.Kind()) // float64
修改值(通过指针)
var x float64 = 3.14
v := reflect.ValueOf(&x) // 必须传递指针
v = v.Elem() // 获取指针指向的值
v.SetFloat(2.718) // 修改值
fmt.Println(x) // 2.718
结构体反射
| 方法 | 说明 |
|---|---|
| NumField() | 字段数量 |
| Field(i) | 获取第i个字段的Value |
| FieldByName(name) | 按名称获取字段 |
| NumMethod() | 方法数量 |
| Method(i) | 获取第i个方法 |
type Person struct {
Name string
Age int
}
p := Person{"Alice", 30}
t := reflect.TypeOf(p)
// 遍历字段
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
fmt.Printf("%s: %s
", field.Name, field.Type)
}
// 调用方法
v := reflect.ValueOf(p)
method := v.MethodByName("Greet")
if method.IsValid() {
method.Call(nil)
}
动态创建实例
// 创建切片实例
t := reflect.SliceOf(reflect.TypeOf(0))
v := reflect.MakeSlice(t, 0, 10)
// 创建map实例
mapType := reflect.MapOf(reflect.TypeOf(""), reflect.TypeOf(0))
m := reflect.MakeMap(mapType)
m.SetMapIndex(reflect.ValueOf("key"), reflect.ValueOf(42))
练习提示:编写一个通用JSON序列化函数,使用反射将任意结构体转换为map[string]interface{},处理嵌套结构体和基本类型。