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
猜你喜欢
- 在服务器端asp程序可以接受html页面上的form传来的参数,那么它又如何实现IE地址参数判断呢?当地址栏没有参数"id"时
- 很棒的新闻发布系统分享给大家,希望大家喜欢。下面就让我们来说一说基于jsp的新闻发布系统,其中使用的技术有JavaBean、fillter、
- 1 PHP官网地址:PHP界面:2 下载官网下载地址:Download PHP 或者点击这里下载3 安装① 按照下图下载 php。
- 大家都知道一些论坛的标题有高亮显示功能,在这里我不讨论也不研究论坛普遍的实现方法,下面是我的实现方法:实现思路:把要高亮显示的标题加上特定标
- 1、什么是AspJpeg?AspJpeg是一款功能强大的基于Microsoft IIS环境的图片处理组件,AspJpeg可以使用很少的代码在
- 好了,下面就是满足你设想的几个主程序,你还可以在实际应用中不断完善和扩充:login.asp' 考生验证<%@&nb
- 这本入门手册是否合适你?我只想告诉你我非常喜欢这本书。我对Microsoft Access的经验足以让我跳过这本傻瓜系列教材,但是实际情况是
- 在JavaScript前端开发工作中,由于浏览器兼容性等问题,我们会经常用到“停止事件冒泡”和“阻止浏览器默认行为”。1..停止事件冒泡//
- 请问如何从ASP连接到Oracle Server?可用下面的代码进行连接: <%@ Lan
- 对于软件来说,每一个新版本的推出都应该是一种进步,不可否认,阿里旺旺2008版相较于之前的版本的确是有很多的进步,但进步的同时却也有着比之前
- 无论安装何版本的mysql,在管理工具的服务中启动mysql服务时都会在中途报错。内容为:在 本地计算机 无法启动mysql服务 错误106
- 首先澄清一个应用场景问题。研究(1)中指出,对于结构复杂的网站,不少设计师们喜欢采用960固定宽度布局。但要注意的是,960并不是万能钥匙,
- 昨天同事无意又谈起了这个老话题,美工和设计师(视觉)有什么不同?以文字排版设计为例,列了下面两个图来说明,可能会有一些启发, 第一个图应该算
- asp使用fso读取驱动器信息:<%vv=drive()response.write vv funct
- 本文列举了兼容 IE 和 FF 的换行 CSS 推荐样式,详细介绍了word-wrap同word-break的区别。兼容 IE 和 FF 的
- 代码如下:Function getTreeRootId(pNodeId) getSQL = "select note_id,par
- 通过亲密性原则,我们可以将一个页面中的元素按照某种逻辑理解上的差异划分成不同的元素组合;再通过对齐原则,使这些不同的元素组合在视觉上看起来彼
- 关于跨域这个话题,很早就答应过要分享,但是因为懒,一直拖着,直到D2上有人谈起了“完美跨域”。“跨域”应该已经算不上什么难题了,只是提起“完
- <%sql = "select * from SMT_addt
- 1、开始->运行,输入SERVICES.MSC到服务里,停止所有Oracle服务; 2、开始->程序->Oracle - OraHome81