go反射那些事儿

memo012 · · 171 次点击 · · 开始浏览    
>该文章始发于公众号【迈莫coding】 >链接:[https://mp.weixin.qq.com/s/vFt06c9herwTrx1LTxNaKg](https://mp.weixin.qq.com/s/vFt06c9herwTrx1LTxNaKg) > go发射第一弹【typeOf使用】 > 链接:[https://mp.weixin.qq.com/s/F8yZyqC5UwoewsX0THqy1w](https://mp.weixin.qq.com/s/F8yZyqC5UwoewsX0THqy1w) > go反射第二弹【valuef使用】 > 链接:[https://mp.weixin.qq.com/s/lgZykTL8ls6aG0OMNSbZMw](https://mp.weixin.qq.com/s/lgZykTL8ls6aG0OMNSbZMw) # 目录 - isNil()/isValid() - 反射创建对象 - Call()函数 - 闲聊 - 欢迎加入我的公众号【迈莫coding】 一起pk大厂 # isNil()/isValid() go语言中,通过 reflect.ValueOf() 方法获取 reflect.Value 对象时,在reflect.Value 对象中提供了一些方法用来判断值是否为空,如下表所示: **示例** ```go package main import ( "fmt" "reflect" ) type User struct{ Name string Age int } func main(){ user := &User{ Name : "迈莫coding", } values := reflect.ValueOf(user) fmt.Println("user对象是否为空:", values.IsNil()) values = values.Elem() fmt.Println("Name字段属性是否存在:", values.FieldByName("Name").IsValid()) } ``` **结果:** ```go user对象是否为空: false Name字段属性是否存在: true ``` **代码说明:** ```go - 第11行:实例化User对象 - 第15行:判断反射对象values是否为空 - 第17行:判断反射对象中"Name"字段属性是否有效 ``` # 反射创建对象 在go语言中,若已知 reflect.Type 类型时,可以通过 reflect.New() 方法进行反射创建实例,但参数注意的是,只能传入 reflect.Type 类型对象。 **示例** ```go package main import ( "fmt" "reflect" ) type User struct{ Name string } func main() { types := reflect.TypeOf(&User{}) values := reflect.New(types) fmt.Println("反射创建出对象的类型和种类:", values.Type(), values.Kind()) } ``` **结果** ```go 反射创建出对象的类型和种类: **main.User ptr ``` # Call()函数 如果反射值对象(reflect.Value)中值的类型为函数时,可以通过 reflect.Value 调用该函数。使用反射调用函数时,需要将参数使用反射值对象的切片 []reflect.Value 构造后传入 Call() 方法中,调用完成时,函数的返回值通过 []reflect.Value 返回。 示例 ```go package main import ( "fmt" "import" ) func add(x, y int) int { return x + y } func main() { addValue := reflect.ValueOf(add) // 构造函数参数, 传入两个整型值 paramList := []reflect.Value{reflect.ValueOf(10), reflect.ValueOf(20)} // 反射调用函数 retList := funcValue.Call(paramList) // 获取第一个返回值, 取整数值 fmt.Println(retList[0].Int()) } ``` **代码说明如下:** ```go 第 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,用户还需要从中取出调用值。因此,反射调用函数的性能问题尤为突出,不建议大量使用反射函数调用。 # 闲聊 - 读完文章,自己是不是和反射的cp率又提高了 - 我是迈莫,欢迎大家和我交流 > 觉得文章写得不错的小伙伴,点个赞👍 鼓励一下吧~ # 欢迎加入我的公众号【迈莫coding】 一起pk大厂 **- 迈莫coding欢迎客官的到来** ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210113132234996.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMDY2MDY2,size_16,color_FFFFFF,t_70#pic_center)

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

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

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