Go中的反射机制

反射是什么东西?

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
在Go 语言中,提供了一种机制在运行时更新变量和检查它们的值、调用它们的方法,但是在编译时并不知道这些变量的具体类型,这称为反射机制。

反射的作用

1.在编写不定传参类型函数的时候,或传入类型过多时,典型应用是对象关系映射

type User struct {gorm.ModelName         stringAge          sql.NullInt64Birthday     *time.TimeEmail        string  `gorm:"type:varchar(100);unique_index"`Role         string  `gorm:"size:255"` // set field size to 255MemberNumber *string `gorm:"unique;not null"` // set member number to unique and not nullNum          int     `gorm:"AUTO_INCREMENT"` // set num to auto incrementableAddress      string  `gorm:"index:addr"` // create index with name `addr` for addressIgnoreMe     int     `gorm:"-"` // ignore this field
}
var users []User
db.Find(&users)

2.不确定调用哪个函数,需要根据某些条件来动态执行

func bridge(funcPtr interface{}, args ...interface{})

第一个参数funcPtr以接口的形式传入函数指针,函数参数args以可变参数的形式传入,bridge函数中可以用反射来动态执行funcPtr函数。

3.对结构体序列化的时候,如果结构体中有指定的Tag,那么就可以使用反射生成相对应的字符串。

type Monster struct {Name string "json:"monsterName""Age int "jsonL"monsterAge""
}

反射的实现

Go的反射基础是接口和类型系统,Go的反射机制是通过接口来进行的。Go 语言在 reflect这个包里定义了各种类型,实现了反射的各种函数,通过它们可以在运行时检测类型的信息、改变类型的值。

1.反射可以将“接口类型变量”转换为“反射类型对象”。(返回的类型为反射类型而非int/float这一些)
反射提供一种机制,允许程序在运行时访问接口内的数据。最经常时候的就是reflect包里的两个方法reflect.Value和reflect.Type。

package mainimport ("fmt""reflect"
)func main() {var Num float64 = 3.14v := reflect.ValueOf(Num)t := reflect.TypeOf(Num)fmt.Println("Reflect : Num.Value = ", v)fmt.Println("Reflect : Num.Type  = ", t)
}
Reflect : Num.Value =  3.14
Reflect : Num.Type  =  float64

上面的例子通过reflect.ValueOf和reflect.TypeOf将接口类型变量分别转换为反射类型对象v和t,v是Num的值,t也是Num的类型。

func TypeOf(i interface{}) Type
func (v Value) Interface() (i interface{})
两个方法的参数类型都是空接口,在整个过程中,当我们调用reflect.TypeOf(x)的时候,当我们调用reflect.TypeOf(x)的时候,Num会被存储在这个空接口中,然后reflect.TypeOf再对空接口进行拆解,将接口类型变量转换为反射类型变量

2.反射可以将“反射类型对象”转换为“接口类型变量”。其实就是与第一条相对应。根据一个 reflect.Value 类型的变量,我们可以使用 Interface 方法恢复其接口类型的值。

package main
import ("fmt""reflect"
)
func main() {var Num = 3.14v := reflect.ValueOf(Num)t := reflect.TypeOf(Num)fmt.Println(v)fmt.Println(t)origin := v.Interface().(float64)fmt.Println(origin)
}

3.如果要修改“反射类型对象”,其值必须是“可写的”。

package main
import ("reflect"
)
func main() {var Num float64 = 3.14v := reflect.ValueOf(Num)v.SetFloat(6.18)
}

这时候就出现panic了:panic: reflect: reflect.Value.SetFloat using unaddressable value … …
报错意思是:SetInt 正在使用一个不能被寻址的值。从 reflect.ValueOf 传入的是 a 的值,而不是 a 的地址,这个 reflect.Value 当然是不能被寻址的。
这是因为反射对象v包含的是副本值,所以无法修改。
我们可以通过CanSet函数来判断反射对象是否可以修改,如下:

package main
import ("fmt""reflect"
)
func main() {var Num float64 = 3.14v := reflect.ValueOf(Num)fmt.Println("v的可写性:", v.CanSet())
}

如果想要修改,那么就将代码改成:

package main
import ("fmt""reflect"
)
func main() {// 声明整型变量a并赋初值var a int = 1024// 获取变量a的反射值对象(a的地址)valueOfA := reflect.ValueOf(&a)// 取出a地址的元素(a的值)valueOfA = valueOfA.Elem()// 修改a的值为1valueOfA.SetInt(1)// 打印a的值fmt.Println(valueOfA.Int())
}

反射的实践

1.通过反射修改内容

var f float64 = 3.14
fmt.Println(f)
p := reflect.ValueOf(&f)
v := p.Elem()
v.SetFloat(6.18)
fmt.Println(f)

reflect.Elem() 方法获取这个指针指向的元素类型。这个获取过程被称为取元素,等效于对指针类型变量做了一个*操作

2.通过反射调用方法

package mainimport ("fmt""reflect"
)func hello() {fmt.Println("Hello world!")
}func main() {hl := hellofv := reflect.ValueOf(hl)fv.Call(nil)
}

反射会使得代码执行效率较慢,原因有

1.涉及到内存分配以及后续的垃圾回收

2.reflect实现里面有大量的枚举,也就是for循环,比如类型之类的

小结

1.反射对象包含了接口变量中存储的值以及类型。

2.如果反射对象中包含的值是原始值,那么可以通过反射对象修改原始值;

3.如果反射对象中包含的值不是原始值(反射对象包含的是副本值或指向原始值的地址),则该反射对象不可以修改。

初探GO中的反射机制相关推荐

  1. 浅说Java中的反射机制(一)

    在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...

  2. java代码安全检测机制_全面解析:java中的反射机制,内含代码验证解析

    什么是反射? 在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功 ...

  3. 根据实例详解Java中的反射机制

    概念: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java ...

  4. formdata 接受参数中带有class 对象_浅析JAVA中的反射机制及对Servlet的优化

    今天来聊聊java中的反射机制,工作以后发现很多东西动不动就要使用反射或者动态代理,如果不能很好的理解反射,那么对于动态代理等一些重要的设计模式就会有种不够通透的感觉. 所谓的反射,就是在运行状态中, ...

  5. java反射机制是什么_java中的反射机制是什么?

    java中的反射机制是什么? 发布时间:2020-05-21 22:45:50 来源:亿速云 阅读:156 作者:鸽子 java:"一切即对象",感觉java语言本身在不断践行着这 ...

  6. java中的反射机制是什么

    给大家介绍一下java中的反射机制,java中反射机制更体现出了java的灵活性.多态.和类之间的耦合性. 1:反射是一种间接操作目标对象的机制,只要给定类的名字,就可以通过反设机制获取所有的类信息. ...

  7. Java中的反射机制详讲

    Java中的反射机制详讲 1.反射机制_介绍_Class对象获取 2.反射机制_动态操作_构造器_方法_属性 3.动态编译_DanamicCompile_反射调用main方法问题 好文推荐:排序.查找 ...

  8. 【反射机制】Java中的反射机制,使用反射机制创建对象、访问属性、方法、构造方法等

    这篇文章主要是整理了Java中的反射机制,包括:反射机制概念.反射机制访问构造方法.反射机制访问普通方法.反射机制访问属性,反射机制访问修饰符. 目录 一.反射机制概念 二.反射机制使用 (1)加载C ...

  9. Python中的反射机制(reflect)

    1.区别标识名与看起来相同的字符串 标识名和看起来相同的字符串,两者在字面上看起来一样,却是两种东西,例如下面的例子中func函数和字符串"func" def func():pri ...

最新文章

  1. ethtool修改网卡队列
  2. 怎样批量调整word 图片大小?
  3. 【C# 调用 Go 语言】0x2 参数、返回值与类型转换
  4. Python运算符优先级
  5. influxDb 异常:{“error“:“retention policy not found: default“}
  6. 常用SHELL软件命令
  7. rect函数_Python基础进阶:从函数到高级魔法方法--Day 6
  8. python乱码大赛_FishC工作室《零基础学python》全套课后题.doc
  9. python程序设计与实验_用于创建实验的Python应用程序和库
  10. win7和手机共享文件和上网
  11. 我的故事登上了Android开发者的官网
  12. 云南省计算机考研排名,考研云南有哪些大学排名
  13. HUAWEI 机试题:最长元音字串的长度
  14. 教你同时分析圆通快递多个单号的物流情况
  15. [射影几何]射影线束画二次曲线
  16. 20200509 Curator入门
  17. Markdown的常用语法(个人总结)
  18. 如何将视频里的音乐提取出来
  19. 前端装逼技巧 108 式(一)—— 打工人
  20. “shadows a parameter“ 和 “error: expected ‘}’ at end of input”

热门文章

  1. 关于开源的RTP——jrtplib的使用(2)
  2. Security Best Practices+Klocwork
  3. 动画交互应用——星球引力
  4. Android中Alarm的机制
  5. Python函数 - - reverse()和reversed()
  6. chrome书签变透明看不清怎么办
  7. linux的头文件下载,Linux内核头文件(linux headers)
  8. 1024专场回顾 | 企业级开源数据库openGauss论坛
  9. Matplotlib的柱状图
  10. 牛顿下降法和梯度下降法(最速下降法)的速度的比较