Go语言反射reflect标准库04-类型创建实例、反射调用函数

通过类型信息创建实例

当已知 reflect.Type 时,可以动态地创建这个类型的实例,实例的类型为指针。例如 reflect.Type 的类型为 int 时,创建 int 的指针,即*int,代码如下:

func main() {
	var a int
	// 获取a的反射类型对象
	typeOfA := reflect.TypeOf(a)
	// 根据反射类型对象创建实例
	aIns := reflect.New(typeOfA)
	// 获取新创建实例的类型和种类
	fmt.Println(aIns.Type(), aIns.Kind())  // *int Ptr
}

代码说明如下:
第 13 行,获取变量 a 的反射类型对象。
第 16 行,使用 reflect.New() 函数传入变量 a 的反射类型对象,创建这个类型的实例值,值以 reflect.Value 类型返回。这步操作等效于:new(int),因此返回的是 *int 类型的实例。
第 19 行,打印 aIns 的类型为 *int,种类为指针。

通过反射调用函数

如果反射值对象(reflect.Value)中值的类型为函数时,可以通过 reflect.Value 调用该函数。使用反射调用函数时,需要将参数使用反射值对象的切片 []reflect.Value 构造后传入 Call() 方法中,调用完成时,函数的返回值通过 []reflect.Value 返回。

下面的代码声明一个加法函数,传入两个整型值,返回两个整型值的和。将函数保存到反射值对象(reflect.Value)中,然后将两个整型值构造为反射值对象的切片([]reflect.Value),使用 Call() 方法进行调用。

反射调用函数:

func add(a, b int) int {
	return a+b
}
func main() {
	// 将函数包装为反射值对象
	valueOfAdd := reflect.ValueOf(add)
	// 构造参数
	args := []reflect.Value{reflect.ValueOf(10), reflect.ValueOf(20)}
	ret := valueOfAdd.Call(args)
	// 将反射值对象转换为int
	fmt.Println(ret[0].Int())
}

代码说明如下:

第 9~12 行,定义一个普通的加法函数。
第 17 行,将 add 函数包装为反射值对象。
第 20 行,将 10 和 20 两个整型值使用 reflect.ValueOf 包装为 reflect.Value,再将反射值对象的切片 []reflect.Value 作为函数的参数。
第 23 行,使用 funcValue 函数值对象的 Call() 方法,传入参数列表 paramList 调用 add() 函数。
第 26 行,调用成功后,通过 retList[0] 取返回值的第一个参数,使用 Int 取返回值的整数值。

提示:
反射调用函数的过程需要构造大量的 reflect.Value 和中间变量,对函数参数值进行逐一检查,还需要将调用参数复制到调用函数的参数内存中。调用完毕后,还需要将返回值转换为reflect.Value,用户还需要从中取出调用值。因此,反射调用函数的性能问题尤为突出,不建议大量使用反射函数调用。

Go语言inject库:依赖注入

参考文章

posted @ 2022-08-16 11:02  专职  阅读(229)  评论(0编辑  收藏  举报