分享
  1. 首页
  2. 文章

golang反射中函数和方法的调用

wowzai · · 24241 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

golang反射中函数和方法的调用

上一篇文章说到了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

反射中调用方法

上面说了在反射中调用函数的例子,接下来我们要谈谈反射中方法的调用。函数和方法可以说其实本质上是相同的,只不过方法与一个"对象"进行了"绑定",方法是"对象"的一种行为,这种行为是对于这个"对象"的一系列操作,例如修改"对象"的某个属性,例如如下:

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) 
}

好了,现在类型和其对应的方法都已经准备好了,那接下来就是如何使用的问题了,我们有了上面调用函数的经验,只需要再了解一点知识就可以使用了,这一点知识就是MethodMethodByName的API,好了,现在都准备好了,我们就看看如何使用吧。

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])
}

prints:

Before: address:0x18245050--name:wowzai i:22
After: address:0x18245050--name:reflection test i:18

需要注意的是上面打印的地址是对象在内存的地址,如果你也运行了这段代码,结果这个地址应该是不同的。

咦,就这样结束了吗?当然不是,细心的读者会发现上面提到的Method好像没用到啊,恩,是的,聪明的你一看API的介绍我相信你就知道如何将上面的代码转换成用Method方法达到同样的效果:

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])

打印的效果和上面的例子相同(地址可能不同),嗯,到这里基本上反射中函数和方法的调用基本说完了,可是真的结束了?是否还有其他办法呢?嗯,聪明的你总能想得到的。

---如有错误,欢迎指正---


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:wowzai

查看原文:golang反射中函数和方法的调用

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
24241 次点击 ∙ 2 赞
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏