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) 创建新实例
如有疑问关注公众号给我留言
wx

关注公众号

©2017-2023 鲁ICP备17023316号-1 Powered by Hugo