初探GO中的反射机制
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中的反射机制相关推荐
- 浅说Java中的反射机制(一)
在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...
- java代码安全检测机制_全面解析:java中的反射机制,内含代码验证解析
什么是反射? 在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功 ...
- 根据实例详解Java中的反射机制
概念: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java ...
- formdata 接受参数中带有class 对象_浅析JAVA中的反射机制及对Servlet的优化
今天来聊聊java中的反射机制,工作以后发现很多东西动不动就要使用反射或者动态代理,如果不能很好的理解反射,那么对于动态代理等一些重要的设计模式就会有种不够通透的感觉. 所谓的反射,就是在运行状态中, ...
- java反射机制是什么_java中的反射机制是什么?
java中的反射机制是什么? 发布时间:2020-05-21 22:45:50 来源:亿速云 阅读:156 作者:鸽子 java:"一切即对象",感觉java语言本身在不断践行着这 ...
- java中的反射机制是什么
给大家介绍一下java中的反射机制,java中反射机制更体现出了java的灵活性.多态.和类之间的耦合性. 1:反射是一种间接操作目标对象的机制,只要给定类的名字,就可以通过反设机制获取所有的类信息. ...
- Java中的反射机制详讲
Java中的反射机制详讲 1.反射机制_介绍_Class对象获取 2.反射机制_动态操作_构造器_方法_属性 3.动态编译_DanamicCompile_反射调用main方法问题 好文推荐:排序.查找 ...
- 【反射机制】Java中的反射机制,使用反射机制创建对象、访问属性、方法、构造方法等
这篇文章主要是整理了Java中的反射机制,包括:反射机制概念.反射机制访问构造方法.反射机制访问普通方法.反射机制访问属性,反射机制访问修饰符. 目录 一.反射机制概念 二.反射机制使用 (1)加载C ...
- Python中的反射机制(reflect)
1.区别标识名与看起来相同的字符串 标识名和看起来相同的字符串,两者在字面上看起来一样,却是两种东西,例如下面的例子中func函数和字符串"func" def func():pri ...
最新文章
- ethtool修改网卡队列
- 怎样批量调整word 图片大小?
- 【C# 调用 Go 语言】0x2 参数、返回值与类型转换
- Python运算符优先级
- influxDb 异常:{“error“:“retention policy not found: default“}
- 常用SHELL软件命令
- rect函数_Python基础进阶:从函数到高级魔法方法--Day 6
- python乱码大赛_FishC工作室《零基础学python》全套课后题.doc
- python程序设计与实验_用于创建实验的Python应用程序和库
- win7和手机共享文件和上网
- 我的故事登上了Android开发者的官网
- 云南省计算机考研排名,考研云南有哪些大学排名
- HUAWEI 机试题:最长元音字串的长度
- 教你同时分析圆通快递多个单号的物流情况
- [射影几何]射影线束画二次曲线
- 20200509 Curator入门
- Markdown的常用语法(个人总结)
- 如何将视频里的音乐提取出来
- 前端装逼技巧 108 式(一)—— 打工人
- “shadows a parameter“ 和 “error: expected ‘}’ at end of input”