golang 反射中调用方法
反射中调用函数
众所周知,golang中的函数是可以像普通的int、float等类型变量那样作为值的,例如:
package main
import "fmt"
func hello() {
fmt.Println("Hello world!")
}
func main() {
hl := hello
hl()
}
prints:
hello world!
既然函数可以像普通的类型变量一样可以的话,那么在反射机制中就和不同的变量一样的,在反射中函数和方法的类型(Type)都是reflect.Func,如果要调用函数的话,可以通过Value的Call方法,例如:
func main() {
hl := hello
fv := reflect.ValueOf(hl)
fmt.Println("fv is reflect.Func ?",fv.Kind() == reflect.Func)
fv.Call(nil)
}
prints:
fv is reflect.Func? true
hello world!
Value的Call方法的参数是一个Value的slice,对应的反射函数类型的参数,返回值也是一个Value的slice,同样对应反射函数类型的返回值。通过这个例子,相信你一看就明白了:
func prints(i int) string {
fmt.Println("i =",i)
return strconv.Itoa(i)
}
func main() {
fv := reflect.ValueOf(prints)
params := make([]reflect.Value,1) //参数
params[0] := reflect.ValueOf(20) //参数设置为20
rs := fv.Call(params) //rs作为结果接受函数的返回值
fmt.Println("result:",rs[0].Interface().(string)) //当然也可以直接是rs[0].Interface()
}
prints:
i = 20
result: 20
------------------------------------------------------------------
上面说了在反射中调用函数的例子,接下来我们要谈谈反射中方法的调用。函数和方法可以说其实本质上是相同的,只不过方法与一个“对象”进行了“绑定”,方法是“对象”的一种行为,这种行为是对于这个“对象”的一系列操作,例如修改“对象”的某个属性,例如如下:
好了,现在类型和其对应的方法都已经准备好了,那接下来就是如何使用的问题了,我们有了上面调用函数的经验,只需要再了解一点知识就可以使用了,这一点知识就是Method和MethodByName的API,好了,现在都准备好了,我们就看看如何使用吧。
type MyType struct {
i int
name string
}
func (mt *MyType) SetI(i int) {
mt.i = i
}
func (mt *MyType) SetName(name string) {
mt.name = name
}
func (mt *MyType) String() string {
return fmt.Sprintf("%p",mt) + "--name:" + mt.name + " i:" + strconv.Itoa(mt.i)
}
func main() {
myType := &MyType{22,"wowzai"}
//fmt.Println(myType) //就是检查一下myType对象内容
//println("---------------")
//mtV := reflect.ValueOf(&myType).Elem()
//fmt.Println("Before:",mtV.MethodByName("String").Call(nil)[0])
//params := make([]reflect.Value,1)
//params[0] = reflect.ValueOf(18)
//mtV.MethodByName("SetI").Call(params)
//params[0] = reflect.ValueOf("reflection test")
//mtV.MethodByName("SetName").Call(params)
//fmt.Println("After:",mtV.MethodByName("String").Call(nil)[0])
mtV := reflect.ValueOf(&myType).Elem()
fmt.Println("Before:",mtV.Method(2).Call(nil)[0])
params := make([]reflect.Value,1)
params[0] = reflect.ValueOf(18)
mtV.Method(0).Call(params)
params[0] = reflect.ValueOf("reflection test")
mtV.Method(1).Call(params)
fmt.Println("After:",mtV.Method(2).Call(nil)[0])
}
需要注意的是上面打印的地址是对象在内存的地址,如果你也运行了这段代码,结果这个地址应该是不同的。
咦,就这样结束了吗?当然不是,细心的读者会发现上面提到的Method好像没用到啊,恩,是的,聪明的你一看API的介绍我相信你就知道如何将上面的代码转换成用Method方法达到同样的效果:
golang 反射中调用方法的更多相关文章
- Lua中“.”调用方法与“:”调用方法的区别
Lua中“.”调用方法与“:”调用方法的区别: ...
- Xlua文件在热更新中调用方法
Xlua文件在热更新中调用方法 public class news : MonoBehaviour { LuaEnv luaEnv;//定义Lua初始变量 void Awake() { luaEnv ...
- C# 知识点笔记:IEnumerable<>的使用,利用反射动态调用方法
IEnumerable<T>的使用 创建一个IEnumerable对象 List<string> fruits = new List<string> { " ...
- C# 反射之调用方法谈
反射的定义 反射提供了描述程序集.模块和类型的对象(Type 类型). 可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性. 如果代码中使用了特性 ...
- 利用java反射动态调用方法,生成grid数据
项目中需要java后台查询并组装前台grid的数据,数据行数不定,数据行定义不定,开始用了最原始的方法,写了几百行,就是前台需要什么字段后台拼接什么字段,java代码冗余量非常大,并且不够灵活,一旦前 ...
- golang通过反射动态调用方法
func Call(m map[string]interface{}, name string, params ...interface{}) ([]reflect.Value, error) { f ...
- SpringCache @Cacheable 在同一个类中调用方法,导致缓存不生效的问题及解决办法
由于项目需要使用SpringCache来做一点缓存,但自己之前没有使用过(其实是没有听过)SpringCache,于是,必须先学习之. 在网上找到一篇文章,比较好,就先学习了,地址是: https:/ ...
- Golang循环中调用go func参数异常分析
项目中,需要循环调用API服务器列表,在循环中使用go func创建协程时遇到了参数失灵的现象. 具体代码如下所示: for _, apiServerAddr := range apiServerAd ...
- 使用dubbo引用和发布服务时出现的异常:HTTP状态500 - 请求处理失败; 嵌套异常是com.alibaba.dubbo.rpc.RpcException:无法在服务cn.e3mall.service.ItemService中调用方法getTbItemById。使用dubbo版本2.5.3在消费者...
异常情况如下: 从异常看,主要是因为TbItem没有序列化: 分析问题: 表现层调用服务端时返回了一个TbItem对象即Java对象,此时这个对象远程调用拿过来必须进行序列化,要进行网络传输必须先要把 ...
随机推荐
- 【UTR #3】量子破碎
一道有趣的题. 看到按位的矩阵运算,如果对FWT比较熟悉的话,会比较容易地想到. 这种形式也就FWT等转移里面有吧--就算有其他的也难构造出来. 然而FWT的矩阵并不是酉矩阵(也就是满足 \(AA^T ...
- max函数结合lambda使用
说明:d.keys() 以及列表可以看做lambda函数的实参,max的判断对象是key的值.最终返回的是使得key的值最大的那个实参.
- BZOJ 2669 Luogu P3160 [CQOI2012]局部极小值 (容斥原理、DP)
题目链接 (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2669 (luogu) https://www.luogu.org/prob ...
- JAVA使用easyexcel操作Excel
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本 ...
- C++入门经典-例4.6-使用重载函数
1:代码如下: // 4.6.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> using ...
- SpringBoot 使用定时任务动态执行任务
import com.patient.core.adapter.CorsFilter; import org.mybatis.spring.annotation.MapperScan; import ...
- centos 系统时间设置
在我们使用CentOS系统的时候,也许时区经常会出现问题,有时候改完之后还是会出错,下面我们就来学习一种方法来改变这个状况.如果没有安装,而你使用的是 CentOS系统 那使用命令 yum insta ...
- TP5 未定义变量:XXX
TP5开发模式下报错级别非常高,哪怕变量未定义都直接抛出异常 应用公共函数文件 路径: application/common.php 在common.php文件写入 // 异常错误报错级别, err ...
- 如何限制修改IP地址;如何禁止显示的本地连接属性
现在很多单位都配置了局域网,为了便于进行网络管理,同时为了提高的登录网络的速度,网管人员一般都为局域网中的每台电脑都指定了IP地址.但是在windows环境下其他用户很容易修改IP地址配置,这样就很容 ...
- java 正则表达式:有丶东西
非常详细 原文地址:https://blog.csdn.net/jeffleo/article/details/52194977