go语言reflect.Type 和 reflect.Value 应用示例详解
作者:RiemannHypothesis 发布时间:2023-07-18 11:28:43
一、使用 reflect.Type 创建实例
在通过 reflect.TypeOf
函数获取到变量的反射类型对象之后,可以通过反射类型对象 reflect.Type
的 New
函数来创建一个新的实例,注意这个实例的类型是 reflect.Type
类型的。
package main
import (
"fmt"
"reflect"
)
func main() {
var zulu int
zuluTypeOf := reflect.TypeOf(zulu)
// 创建类型实例
zuluIntPtr := reflect.New(zuluTypeOf)
fmt.Printf("%T\n", zuluIntPtr)
fmt.Printf("%v, %v\n", zuluIntPtr.Type(), zuluIntPtr.Kind())
}
执行上述代码,输出结果如下:
reflect.Value
*int, ptr
二、使用 reflect.Value 调用函数
在 Go 语言的函数 讲到 Go 中函数是一等公民,函数可以保存在变量中,当 reflect.ValueOf
获取的是一个函数类型变量的反射值对象时,可以通过 reflect.Value
的 Call
方法调用该函数
使用反射调用函数需要将参数使用反射值对象的切片 []reflect.Value
构造后传入 Call
方法中,调用之后再通过切片 []reflect.Value
的形式返回函数的返回值。
函数只有一个返回值的情况
定义一个 add 函数,该函数有两个入参和一个返回值,先获取函数类型变量的反射值对象,再利用反射值对象调用 Call
函数,并将函数变量中函数的入参以 reflect.Value
类型切片的形式作为 Call
函数的入参即可获取函数变量中函数调用的结果。
package main
import (
"fmt"
"reflect"
)
func main() {
// 定义一个变量保存 add 函数
var victor func(x, y int) (sum int) = add
// 获取 函数变量的反射值对象
victorValueOf := reflect.ValueOf(victor)
// 构造 []reflect.Value 切片参数列表
paramValueOfSlice := []reflect.Value{reflect.ValueOf(3), reflect.ValueOf(8)}
// 调用函数
var resValueOfSlice []reflect.Value = victorValueOf.Call(paramValueOfSlice)
// 遍历
fmt.Printf("%v\n", resValueOfSlice[0])
fmt.Printf("%T\n", resValueOfSlice[0])
}
func add(x, y int) (sum int) {
sum = x + y
return
}
执行上述代码,输出结果如下:
11
reflect.Value
函数有两个或者多个返回值的情况
定义一个 div 函数,该函数有两个入参和两个返回值,仍然是先获取函数类型变量的反射值对象,再利用反射值对象调用 Call
函数,并将函数变量中函数的入参以 reflect.Value
类型切片的形式作为 Call
函数的入参即可获取函数变量中函数调用的结果。
该函数调用结果的切片中含有两个元素,且这两个元素的类型都是 reflect.Value
。
package main
import (
"fmt"
"reflect"
)
func main() {
// 定义一个变量保存 add 函数
var victor func(x, y int) (sum int, ok bool) = div
// 获取 函数变量的反射值对象
victorValueOf := reflect.ValueOf(victor)
fmt.Println("当除数非 0 的情况:")
// 构造 []reflect.Value 切片参数列表
paramValueOfSlice := []reflect.Value{reflect.ValueOf(8), reflect.ValueOf(2)}
// 调用函数
var resValueOfSlice []reflect.Value = victorValueOf.Call(paramValueOfSlice)
// 返回值切片长度
fmt.Printf("返回值切片长度为:%v\n", len(resValueOfSlice))
for i := 0; i < len(resValueOfSlice); i++ {
fmt.Printf("%v, %T\n", resValueOfSlice[i], resValueOfSlice[i])
}
fmt.Println()
fmt.Println("当除数为 0 的情况:")
// 构造 []reflect.Value 切片参数列表
paramValueOfSlice2 := []reflect.Value{reflect.ValueOf(3), reflect.ValueOf(0)}
// 调用函数
var resValueOfSlice2 []reflect.Value = victorValueOf.Call(paramValueOfSlice2)
// 返回值切片长度
fmt.Printf("返回值切片长度为:%v\n", len(resValueOfSlice2))
for i := 0; i < len(resValueOfSlice2); i++ {
fmt.Printf("%v, %T\n", resValueOfSlice2[i], resValueOfSlice2[i])
}
}
func div(x, y int) (res int, ok bool) {
if y == 0 {
res = 0
ok = false
} else {
res = x / y
ok = true
}
return
}
执行上述代码,输出结果如下:
返回值切片长度为:2
4, reflect.Value
true, reflect.Value
当除数为 0 的情况:
返回值切片长度为:2
0, reflect.Value
false, reflect.Value
不管是函数只有一个返回值还是多个返回值的情况,使用反射值对象调用 Call
函数获取到的函数变量中函数的调用结果都是 reflect.Value
类型的,要想获取原类型的数据,还需要将 reflect.Value
再转换成原类型。
来源:https://juejin.cn/post/7136193221796823071


猜你喜欢
- 其实这个问题落伍谈了n次了其中care4也说了两次所以如果你有问题最好先搜索一下 说不定问题早有人解决了http://www.im286.c
- jQuery之所以如此流行并被从大公司到个人博客的几乎每个人都广泛使用,是因为它上手和使用相当简单,而且为我们提供了一些人都不知道的相当棒的
- 1.背景一直苦恼于本地机器和服务器上都要配置一些机器学习方面的环境,今天花了点时间研究了下Jupter notebook远程访问服务器,所以
- 在这个项目中,我们将创建一个停车位计数器。我们会发现总共有多少辆车,以及有多少停车位是空的。关于本教程最好的一点是,我们将使用基本的图像处理
- 阅读目录tcp协议:流式协议(以数据流的形式通信传输)、安全协议(收发信息都需收到确认信息才能完成收发,是一种双向通道的通信)tcp协议在O
- 如何进行 Python 性能优化,是本文探讨的主要问题。本文会涉及常见的代码优化方法,性能优化工具的使用以及如何诊断代码的性能瓶颈等内容,希
- 在pytorch的CNN代码中经常会看到x.view(x.size(0), -1)首先,在pytorch中的view()函数就是用来改变te
- pandas中对DataFrame筛选数据的方法有很多的,以后会后续进行补充,这里只整理遇到错误的情况。1.使用布尔型DataFrame对数
- 一、“无”的哲学佛家讲究“因果报应”,有果必有应。此段看似与主题没有血缘关系,实际讲的是“因”。我个人比较喜欢老子的道家思想,并喜欢以其思想
- PHP的类是单一继承模式,也就是每个类只能继承一个父类(基类)。但有时需要引入更多通用(共用)的方法,同时这些方法又不适合集成到基类。那么这
- 不多说,直接上代码from hdfs import Clientimport pandas as pdHDFSHOST = "ht
- 前言登录跳转:不同的用户在登录成功之后跳转到不同的网页当中例如:网站管理员登录成功后跳转到网站后台,vip用户登录成功后跳转到vip页面准备
- 当你连接到MySQL服务器时,你应使用一个密码。密码不以明文在上传输。客户端连接序列中的密码处理在MySQL 4.1.1中已经升级,很安全。
- 即使MyISAM表格式非常可靠(SQL语句对表做的所有改变在语句返回之前被写下),如果下列任何事件发生,你依然可以获得损坏的表:&m
- 首先,创建一个存储过程 get_clob: t_name:要查询的表名;f_name:要查询的字段名;u_id:表的主键,查询条件;l_po
- oracle 的表空间实例详解查询表空间SELECT UPPER(F.TABLESPACE_NAME) "表空间名",
- excel 文件内容如下:读取excel内容:import xlrdfrom datetime import datetimefrom xl
- ROSE是直接从UML发展而诞生的设计工具,它的出现就是为了对UML建模的支持,ROSE一开始没有对数据库端建模的支持,但是在现在的版本中已
- 缩进和SQL乱码及SQL包含变量1.在 PYCHARM 中只要 拉选块之后,按下tab键,整个块就会缩进,shift + tab
- 加入CDC的这段日子里,工作中积累的小心得都密密麻麻的收在册子里。恰逢近期的校园招聘正如火如荼的展开着,借此机会,我把这一些不太成熟的小想法