Go语言的 reflect
模块提供了强大的反射功能,允许程序在运行时检查类型信息、操作变量值及调用方法。以下是对 reflect
模块核心方法的详细说明及示例:
1. 获取类型信息
reflect.TypeOf
获取变量的类型信息,返回 reflect.Type
对象。
package main
import (
"fmt"
"reflect"
)
func main() {
var x int = 42
t := reflect.TypeOf(x)
fmt.Println(t) // 输出: int
}
2. 获取值信息
reflect.ValueOf
获取变量的值信息,返回 reflect.Value
对象。
func main() {
x := 42
v := reflect.ValueOf(x)
fmt.Println(v) // 输出: 42
}
3. 从 Value
中获取实际值
Value.Interface()
将 Value
转换为 interface{}
,需类型断言。
func main() {
x := 42
v := reflect.ValueOf(x)
val := v.Interface().(int)
fmt.Println(val) // 输出: 42
}
Value.Int()
, Value.String()
, 等
直接获取基础类型的值(需类型匹配)。
func main() {
v := reflect.ValueOf(42)
fmt.Println(v.Int()) // 输出: 42
s := reflect.ValueOf("hello")
fmt.Println(s.String()) // 输出: hello
}
4. 检查类型种类
Type.Kind()
和 Value.Kind()
返回类型的底层种类(如 int
, struct
, slice
)。
func main() {
x := 42
t := reflect.TypeOf(x)
fmt.Println(t.Kind()) // 输出: int
v := reflect.ValueOf(x)
fmt.Println(v.Kind()) // 输出: int
}
5. 操作结构体字段
Type.NumField()
和 Value.Field(i)
遍历结构体的字段。
type Person struct {
Name string
Age int
}
func main() {
p := Person{"Alice", 30}
t := reflect.TypeOf(p)
v := reflect.ValueOf(p)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
fmt.Printf("%s: %v\n", field.Name, value)
}
// 输出:
// Name: Alice
// Age: 30
}
6. 调用方法
Value.MethodByName
和 Value.Call
动态调用结构体的方法。
type Math struct{}
func (m Math) Add(a, b int) int {
return a + b
}
func main() {
m := Math{}
v := reflect.ValueOf(m)
method := v.MethodByName("Add")
args := []reflect.Value{reflect.ValueOf(3), reflect.ValueOf(5)}
result := method.Call(args)
fmt.Println(result[0].Int()) // 输出: 8
}
7. 修改值
Value.Elem()
和 Value.Set
修改指针指向的值(需确保可设置)。
func main() {
x := 42
v := reflect.ValueOf(&x).Elem()
v.SetInt(43)
fmt.Println(x) // 输出: 43
}
8. 创建实例
reflect.New
根据类型创建新实例的指针。
func main() {
t := reflect.TypeOf(0) // int 类型
v := reflect.New(t) // 创建 *int
v.Elem().SetInt(100)
fmt.Println(v.Elem().Int()) // 输出: 100
}
9. 处理切片和映射
reflect.MakeSlice
和 reflect.MakeMap
动态创建切片或映射。
func main() {
// 创建切片
sliceType := reflect.TypeOf([]int(nil))
slice := reflect.MakeSlice(sliceType, 0, 5)
slice = reflect.Append(slice, reflect.ValueOf(1), reflect.ValueOf(2))
fmt.Println(slice) // 输出: [1 2]
// 创建映射
mapType := reflect.TypeOf(map[string]int{})
m := reflect.MakeMap(mapType)
key := reflect.ValueOf("a")
value := reflect.ValueOf(100)
m.SetMapIndex(key, value)
fmt.Println(m) // 输出: map[a:100]
}
10. 处理函数
reflect.FuncOf
和 reflect.MakeFunc
动态创建函数。
func main() {
// 定义函数类型: func(int, int) int
funcType := reflect.FuncOf(
[]reflect.Type{reflect.TypeOf(0), reflect.TypeOf(0)},
[]reflect.Type{reflect.TypeOf(0)},
false,
)
// 实现函数逻辑
adder := reflect.MakeFunc(funcType, func(args []reflect.Value) []reflect.Value {
a := args[0].Int()
b := args[1].Int()
return []reflect.Value{reflect.ValueOf(a + b)}
})
// 调用动态函数
result := adder.Call([]reflect.Value{reflect.ValueOf(3), reflect.ValueOf(5)})
fmt.Println(result[0].Int()) // 输出: 8
}
11. 检查是否可设置
Value.CanSet()
验证 Value
是否可修改。
func main() {
x := 42
v := reflect.ValueOf(x)
fmt.Println(v.CanSet()) // 输出: false(非指针传递)
v = reflect.ValueOf(&x).Elem()
fmt.Println(v.CanSet()) // 输出: true
}
总结
- 核心方法:
- 类型/值获取:
TypeOf
,ValueOf
- 结构体操作:
NumField
,Field
,MethodByName
- 值修改:
Elem
,Set
,CanSet
- 动态创建:
New
,MakeSlice
,MakeMap
,MakeFunc
- 类型/值获取:
- 适用场景:
- 序列化/反序列化(如JSON、XML解析)
- ORM框架中的动态模型处理
- 依赖注入或动态函数调用
- 注意事项:
- 反射代码性能较低,应避免频繁使用。
- 操作未导出字段需谨慎,可能破坏封装性。
- 类型不匹配会导致运行时panic,需提前检查
Kind
。