reflect 包基本用法
reflect 包提供了运行时反射功能,允许程序操作任意类型的对象。
获取类型信息
package main
import (
"fmt"
"reflect"
)
func main() {
// 获取变量的类型
var x int = 42
t := reflect.TypeOf(x)
fmt.Printf("类型: %v\n", t)
fmt.Printf("类型名: %v\n", t.Name())
fmt.Printf("类型种类: %v\n", t.Kind())
// 获取指针的类型
var p *int = &x
pt := reflect.TypeOf(p)
fmt.Printf("指针类型: %v\n", pt)
fmt.Printf("指针指向的类型: %v\n", pt.Elem())
}
获取和设置值
package main
import (
"fmt"
"reflect"
)
func main() {
// 获取值
var x int = 42
v := reflect.ValueOf(x)
fmt.Printf("值: %v\n", v)
fmt.Printf("类型: %v\n", v.Type())
fmt.Printf("种类: %v\n", v.Kind())
// 通过接口获取原始值
original := v.Interface().(int)
fmt.Printf("原始值: %v\n", original)
// 设置值(需要指针)
var y int = 10
pv := reflect.ValueOf(&y).Elem()
fmt.Printf("修改前: %v\n", y)
pv.SetInt(100)
fmt.Printf("修改后: %v\n", y)
// 检查是否可设置
fmt.Printf("是否可设置: %v\n", pv.CanSet())
}
结构体反射
package main
import (
"fmt"
"reflect"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
private string
}
func main() {
p := Person{Name: "张三", Age: 25}
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, 值: %v, tag: %s\n",
field.Name, field.Type, value, field.Tag.Get("json"))
}
// 通过名称获取字段
if nameField, ok := t.FieldByName("Name"); ok {
fmt.Printf("Name 字段类型: %v\n", nameField.Type)
}
}
调用函数
package main
import (
"fmt"
"reflect"
)
func Add(a, b int) int {
return a + b
}
func Greet(name string) string {
return "Hello, " + name
}
func main() {
// 获取函数
fn := reflect.ValueOf(Add)
// 准备参数
args := []reflect.Value{
reflect.ValueOf(10),
reflect.ValueOf(20),
}
// 调用函数
results := fn.Call(args)
fmt.Printf("10 + 20 = %v\n", results[0])
// 调用 Greet
greetFn := reflect.ValueOf(Greet)
greetResults := greetFn.Call([]reflect.Value{reflect.ValueOf("World")})
fmt.Printf("%v\n", greetResults[0])
}
创建新实例
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string
Age int
}
func main() {
// 通过反射创建结构体实例
t := reflect.TypeOf(User{})
// 创建指针类型的值
ptr := reflect.New(t)
fmt.Printf("类型: %v\n", ptr.Type())
fmt.Printf("指向的类型: %v\n", ptr.Elem().Type())
// 设置字段值
elem := ptr.Elem()
elem.FieldByName("Name").SetString("李四")
elem.FieldByName("Age").SetInt(30)
// 转换为原始类型
user := ptr.Interface().(*User)
fmt.Printf("User: %+v\n", user)
}
切片的反射操作
package main
import (
"fmt"
"reflect"
)
func main() {
// 创建切片
sliceType := reflect.TypeOf([]int{})
slice := reflect.MakeSlice(sliceType, 0, 10)
// 追加元素
for i := 0; i < 5; i++ {
slice = reflect.Append(slice, reflect.ValueOf(i))
}
fmt.Printf("切片长度: %d\n", slice.Len())
fmt.Printf("切片容量: %d\n", slice.Cap())
// 遍历切片
for i := 0; i < slice.Len(); i++ {
fmt.Printf("索引 %d: %v\n", i, slice.Index(i))
}
// 转换为原始类型
ints := slice.Interface().([]int)
fmt.Printf("原始切片: %v\n", ints)
}
Map 的反射操作
package main
import (
"fmt"
"reflect"
)
func main() {
// 创建 map
mapType := reflect.TypeOf(map[string]int{})
m := reflect.MakeMap(mapType)
// 设置键值对
key := reflect.ValueOf("one")
value := reflect.ValueOf(1)
m.SetMapIndex(key, value)
m.SetMapIndex(reflect.ValueOf("two"), reflect.ValueOf(2))
m.SetMapIndex(reflect.ValueOf("three"), reflect.ValueOf(3))
// 遍历 map
for _, k := range m.MapKeys() {
v := m.MapIndex(k)
fmt.Printf("%v: %v\n", k, v)
}
// 删除键值对
m.SetMapIndex(reflect.ValueOf("two"), reflect.Value{})
// 转换为原始类型
originalMap := m.Interface().(map[string]int)
fmt.Printf("原始 map: %v\n", originalMap)
}
总结
| 功能 | 方法 | 说明 |
|---|---|---|
| 获取类型 | TypeOf(v) |
获取值的类型信息 |
| 获取值 | ValueOf(v) |
获取值的反射对象 |
| 类型信息 | Type.Name(), Type.Kind() |
获取类型名称和种类 |
| 值操作 | Value.Int(), Value.String() |
获取具体类型的值 |
| 修改值 | Value.SetInt(), Value.SetString() |
设置值(需要可寻址) |
| 结构体 | NumField(), Field(i) |
遍历结构体字段 |
| 调用函数 | Value.Call(args) |
动态调用函数 |
| 创建实例 | reflect.New(t) |
创建新实例 |