2.reflect.TypeOf()
Go反射主要与interface
相关,只有interface
类型才有反射一说。
反射就是用来访问存储在接口变量内部类型、值的一种机制。
直接获取到变量内部的信息
Go的reflect
包提供了两种方法,可以访问接口变量内容reflect.TypeOf()
和 reflect.ValueOf()
。
1. reflect.TypeOf(i interface{}) Type 方法
//src\reflect\type.go// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
func TypeOf(i interface{}) Type {eface := *(*emptyInterface)(unsafe.Pointer(&i)) return toType(eface.typ)
}func toType(t *rtype) Type {if t == nil {return nil}return t
}
2 TypeOf()返回内容
由于TypeOf()
入参为空接口。在将一个接口传递给TypeOf时,可能会发生类型转换。
i
不是空接口,即iface
对象。会产生convI2E
转换,将iface
的动态类型赋值为eface
动态类型。i
本身就是空接口。直接赋值。- 将
eface.typ
即入参的动态类型转换为Type
接口类型。(接口类型为Type
,值为eface.typ
)
3 总结
TypeOf
返回入一个iface
变量。iface.tab
为reflect.Type
接口类型。iface.data
为入参的动态类型
。TypeOf
不关心入参的值。
type iface struct {tab *itabdata unsafe.Pointer
}
type itab struct {inter *interfacetype_type *_typehash uint32 // copy of _type.hash. Used for type switches._ [4]bytefun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}
type interfacetype struct {typ _typepkgpath namemhdr []imethod
}
// reflect.emptyInterface == runtime.eface
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {typ *rtypeword unsafe.Pointer
}
4. TypeOf实现原理
5 type person struct {6 name string
7 age int32
8 }
23 var var_type reflect.Type = reflect.TypeOf(var_person)
对应汇编
0x00e0 00224 (reflect.go:23) MOVL "".var_person+1800(SP), AX
0x00e7 00231 (reflect.go:23) MOVQ "".var_person+1792(SP), CX
0x00ef 00239 (reflect.go:23) PCDATA $2, $3
0x00ef 00239 (reflect.go:23) MOVQ "".var_person+1784(SP), DX
0x00f7 00247 (reflect.go:23) PCDATA $2, $0
0x00f7 00247 (reflect.go:23) PCDATA $0, $4//临时变量autotmp_77,保存var_person
0x00f7 00247 (reflect.go:23) MOVQ DX, ""..autotmp_77+2024(SP) //name字符串存放地址
0x00ff 00255 (reflect.go:23) MOVQ CX, ""..autotmp_77+2032(SP) //name字符串长度
0x0107 00263 (reflect.go:23) MOVL AX, ""..autotmp_77+2040(SP) //age// 构造一个eface, 调用runtime.convT2E(), 准备两个参数入栈,1)动态类型。2)值。
0x010e 00270 (reflect.go:23) PCDATA $2, $1
0x010e 00270 (reflect.go:23) LEAQ type."".person(SB), AX //将person类型放入AX
0x0115 00277 (reflect.go:23) PCDATA $2, $0
0x0115 00277 (reflect.go:23) MOVQ AX, (SP) //person类型压入栈 **
0x0119 00281 (reflect.go:23) PCDATA $2, $1
0x0119 00281 (reflect.go:23) PCDATA $0, $3
0x0119 00281 (reflect.go:23) LEAQ ""..autotmp_77+2024(SP), AX //将临时变量autotmp_77,放入AX
0x0121 00289 (reflect.go:23) PCDATA $2, $0
0x0121 00289 (reflect.go:23) MOVQ AX, 8(SP) //将临时变量autotmp_77入栈 **// 调用convT2E(),构造一个eface变量
0x0126 00294 (reflect.go:23) CALL runtime.convT2E(SB) //将临时变量转换为eface变量。**
0x012b 00299 (reflect.go:23) PCDATA $2, $1
0x012b 00299 (reflect.go:23) MOVQ 24(SP), AX //返回值
0x0130 00304 (reflect.go:23) MOVQ 16(SP), CX //返回值// 临时变量autotmp_83保存eface对象
0x0135 00309 (reflect.go:23) MOVQ CX, ""..autotmp_83+1304(SP) //动态类型==person
0x013d 00317 (reflect.go:23) MOVQ AX, ""..autotmp_83+1312(SP) //变量值==var_person
0x0145 00325 (reflect.go:23) PCDATA $0, $5// 入参i interface{}即为一个eface对象,将得到的eface变量设置给入参
0x0145 00325 (reflect.go:23) MOVQ CX, reflect.i+888(SP) //将临时eface变量设置到TypeOf()入参i. eface动态类型
0x014d 00333 (reflect.go:23) PCDATA $2, $0
0x014d 00333 (reflect.go:23) MOVQ AX, reflect.i+896(SP) //将临时eface变量设置到TypeOf()入参i. eface值。
0x0155 00341 (reflect.go:23) XORPS X0, X0
0x0158 00344 (reflect.go:23) MOVUPS X0, "".~R0+680(SP) //返回值清零
0x0160 00352 (reflect.go:23) XCHGL AX, AX //写屏障
0x0161 00353 (reflect.go:23) XORPS X0, X0
0x0164 00356 (reflect.go:23) MOVUPS X0, reflect.eface·3+1144(SP) //置空TypeOf函数中临时变量eface.0x016c 00364 ($GOROOT/src/reflect/type.go:1375) PCDATA $2, $1
0x016c 00364 ($GOROOT/src/reflect/type.go:1375) LEAQ reflect.i+888(SP), AX // 动态类型 struct person放入AX
0x0174 00372 ($GOROOT/src/reflect/type.go:1375) PCDATA $2, $0
0x0174 00372 ($GOROOT/src/reflect/type.go:1375) TESTB AL, (AX) //确保不是nil接口
0x0176 00374 ($GOROOT/src/reflect/type.go:1375) PCDATA $2, $1
0x0176 00374 ($GOROOT/src/reflect/type.go:1375) MOVQ reflect.i+896(SP), AX // 变量值 var_person到 AX
0x017e 00382 ($GOROOT/src/reflect/type.go:1375) PCDATA $2, $4
0x017e 00382 ($GOROOT/src/reflect/type.go:1375) PCDATA $0, $3
0x017e 00382 ($GOROOT/src/reflect/type.go:1375) MOVQ reflect.i+888(SP), CX // 动态类型struct person 到CX//设置临时变量eface
0x0186 00390 ($GOROOT/src/reflect/type.go:1375) MOVQ CX, reflect.eface·3+1144(SP) //设置临时变量eface的动态类型
0x018e 00398 ($GOROOT/src/reflect/type.go:1375) PCDATA $2, $2
0x018e 00398 ($GOROOT/src/reflect/type.go:1375) MOVQ AX, reflect.eface·3+1152(SP) //设置临时变量的值// 调用toType,将eface.typ,即动态类型转换为Type接口。1376 toType(eface.typ)
0x0196 00406 ($GOROOT/src/reflect/type.go:1376) PCDATA $2, $0
0x0196 00406 ($GOROOT/src/reflect/type.go:1376) PCDATA $0, $6
0x0196 00406 ($GOROOT/src/reflect/type.go:1376) MOVQ CX, reflect.t+216(SP) // 将动态类型,即struct person设置给临时变量t
0x019e 00414 ($GOROOT/src/reflect/type.go:1376) XORPS X0, X0
0x01a1 00417 ($GOROOT/src/reflect/type.go:1376) MOVUPS X0, "".~R0+824(SP) //清零返回值
0x01a9 00425 ($GOROOT/src/reflect/type.go:1376) XCHGL AX, AX //写屏障// func toType(t *rtype) Type
0x01aa 00426 ($GOROOT/src/reflect/type.go:3004) CMPQ reflect.t+216(SP), $0 // 判断是否nil类型
0x01b3 00435 (:0) JNE 442
0x01b5 00437 (:0) JMP 6716
0x01ba 00442 ($GOROOT/src/reflect/type.go:3007) PCDATA $2, $1
0x01ba 00442 ($GOROOT/src/reflect/type.go:3007) PCDATA $0, $3
0x01ba 00442 ($GOROOT/src/reflect/type.go:3007) MOVQ reflect.t+216(SP), AX // 将动态类型即struct person设置到AX
0x01c2 00450 ($GOROOT/src/reflect/type.go:3007) MOVQ AX, ""..autotmp_78+280(SP) //动态类型赋值给临时变量 autotmp_78,没啥用
0x01ca 00458 ($GOROOT/src/reflect/type.go:1376) PCDATA $2, $4//重点逻辑// 临时变量autotmp_84,类型是Type接口,即iface变量。
0x01ca 00458 ($GOROOT/src/reflect/type.go:1376) LEAQ go.itab.*reflect.rtype,reflect.Type(SB), CX//设置iface.tab为go.itab.*reflect.rtype
0x01d1 00465 ($GOROOT/src/reflect/type.go:1376) MOVQ CX, ""..autotmp_84+1288(SP) //有0x01ba知道AX中放的是struct person的类型,//设置iface.data为入参的动态类型部分。
0x01d9 00473 ($GOROOT/src/reflect/type.go:1376) MOVQ AX, ""..autotmp_84+1296(SP) // 设置返回值接口变量值部分设置为动态类型 0x01e1 00481 ($GOROOT/src/reflect/type.go:1376) PCDATA $2, $1
0x01e1 00481 ($GOROOT/src/reflect/type.go:1376) PCDATA $0, $7
0x01e1 00481 ($GOROOT/src/reflect/type.go:1376) MOVQ CX, "".~R0+824(SP) // 接口类型Type
0x01e9 00489 ($GOROOT/src/reflect/type.go:1376) PCDATA $2, $0
0x01e9 00489 ($GOROOT/src/reflect/type.go:1376) MOVQ AX, "".~R0+832(SP) // 接口值即动态类型
0x01f1 00497 ($GOROOT/src/reflect/type.go:1376) JMP 499
0x01f3 00499 (reflect.go:23) PCDATA $2, $1
0x01f3 00499 (reflect.go:23) MOVQ "".~R0+832(SP), AX
0x01fb 00507 (reflect.go:23) PCDATA $0, $3
0x01fb 00507 (reflect.go:23) MOVQ "".~R0+824(SP), CX
0x0203 00515 (reflect.go:23) MOVQ CX, ""..autotmp_85+1272(SP)
0x020b 00523 (reflect.go:23) MOVQ AX, ""..autotmp_85+1280(SP)
0x0213 00531 (reflect.go:23) MOVQ CX, "".~R0+680(SP)
0x021b 00539 (reflect.go:23) MOVQ AX, "".~R0+688(SP)
0x0223 00547 (reflect.go:23) JMP 549
0x0225 00549 (reflect.go:23) PCDATA $0, $8
0x0225 00549 (reflect.go:23) MOVQ CX, "".var_type+840(SP)
0x022d 00557 (reflect.go:23) PCDATA $2, $0
0x022d 00557 (reflect.go:23) MOVQ AX, "".var_type+848(SP)
type."".person
type."".person SRODATA size=1600x0000 18 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................0x0010 0a 75 d3 7f 07 08 08 19 00 00 00 00 00 00 00 00 .u..............0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0x0040 02 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 ................0x0050 00 00 00 00 01 00 01 00 40 00 00 00 00 00 00 00 ........@.......0x0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0x0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0x0080 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00 ........ .......0x0090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................rel 24+8 t=1 type..alg."".person+0rel 32+8 t=1 runtime.gcbits.01+0rel 40+4 t=5 type..namedata.*main.person-+0rel 44+4 t=5 type.*"".person+0rel 48+8 t=1 type..importpath."".+0rel 56+8 t=1 type."".person+96rel 80+4 t=5 type..importpath."".+0rel 96+8 t=1 type..namedata.name-+0rel 104+8 t=1 type.string+0rel 120+8 t=1 type..namedata.age-+0rel 128+8 t=1 type.int32+0rel 144+4 t=5 type..namedata.Test_MethodByName1.+0rel 148+4 t=24 type.func()+0rel 152+4 t=24 "".(*person).Test_MethodByName1+0rel 156+4 t=24 "".person.Test_MethodByName1+0
5 reflect.rtype
== runtime._type
// rtype must be kept in sync with ../runtime/type.go:/^type._type.
type rtype struct { //共48字节size uintptr // 8 字节ptrdata uintptr // 8 字节 number of bytes in the type that can contain pointershash uint32 // 4 字节 hash of type; avoids computation in hash tablestflag tflag // 1 字节 extra type information flagsalign uint8 // 1 字节 alignment of variable with this typefieldAlign uint8 // 1 字节 alignment of struct field with this typekind uint8 // 1 字节 enumeration for Calg *typeAlg // 8 字节 algorithm tablegcdata *byte // 8 字节 garbage collection datastr nameOff // 4 字节 string formptrToThis typeOff // 4 字节 type for pointer to this type, may be zero
}
2.reflect.TypeOf()相关推荐
- go语言反射机制、reflect.TypeOf、 reflect.ValueOf、字符串处理(详解)
文章目录 前言 一.反射基本概念 ①go语言反射为何而生? ②反射弊端 ③怎样使用反射机制? 一.反射使用到的库及常用函数 ①用到的库 ②常用的字符串处理函数 (1) 将字符串加载为固定的类型strc ...
- Golang反射机制的实现分析——reflect.Type方法查找和调用
在<Golang反射机制的实现分析--reflect.Type类型名称>一文中,我们分析了Golang获取类型基本信息的流程.本文将基于上述知识和经验,分析方法的查找和调用.(转载请指明出 ...
- Golang反射机制的实现分析——reflect.Type类型名称
现在越来越多的java.php或者python程序员转向了Golang.其中一个比较重要的原因是,它和C/C++一样,可以编译成机器码运行,这保证了执行的效率.在上述解释型语言中,它们都支持了&quo ...
- Golang的反射reflect深入理解和示例
[TOC] Golang的反射reflect深入理解和示例 [记录于2018年2月] 编程语言中反射的概念 在计算机科学领域,反射是指一类应用,它们能够自描述和自控制.也就是说,这类应用通过采用某种机 ...
- Go Reflect
最近在看一些go语言标准库以及第三方库的源码时,发现go的reflect被大量使用,虽然反射的机制大多数语言都支持,但好像都没有go一样这么依赖反射的特性.个人觉得,reflect使用如此频繁的一个重 ...
- golang reflect
go语言中reflect反射机制.详细原文:地址 接口值到反射对象 package mainimport ("fmt""reflect" )func main( ...
- GO语言基础之reflect反射
反射reflection 1. 反射可以大大的提高程序的灵活性,使得 interface{} 有更大的发挥余地 2. 反射使用 TypeOf 和 ValueOf 函数从接口中获取目标对象信息 3. 反 ...
- Go 语言编程 — reflect 反射机制
目录 文章目录 目录 为什么需要反射? reflect 包 通过 reflect.TypeOf() 获取对象的反射类型 reflect.Type 通过 reflect.Elem() 获取指针所指向的对 ...
- golang 反射 reflect包 struct相互填充
最近在用Golang写一些简单的业务,经常需要在两类相似的结构体之间相互填充数据,如果struct只有少数几个field,相互赋值还好:struct有很多field的,实例代码如下: type Req ...
- golang reflect Pointer 获取 传入的interface信息
使用反射可以获取到数据的类型信息,reflect.TypeOf()返回的数据类型如下: type rtype struct {size uintptrptrdata uintptr // number ...
最新文章
- beats x连android手机吗,beats x 能连安卓手机吗?
- 高性能Server---Reactor模型
- 数据库面试题【十六、优化长难的查询语句】
- K8s普通用户配置权限解决User “system:anonymous“ cannot list nodes at the cluster scope
- 三种复方门冬维甘滴眼液的抗菌能力比较
- 关于Fiori application里取Account image的Odata request是否会阻塞UI的问题讨论
- osx php7 imagick,[PHP] MacOS 自带php环境安装imagick扩展踩坑记录 | 码农部落
- k均值算法 二分k均值算法_使用K均值对加勒比珊瑚礁进行分类
- 研究显示每天工作超8小时得心脏病概率增加80%,生命很重要,工作不要那个累。
- linux内核网络新特性,Linux内核4.4版本带来的网络新特性
- 使用采用 Android* OS 的英特尔® 集成性能基元
- a标签去掉下划线_html常用标签、包含关系、常用术语,以及网页设计中的字体分类
- RabbitMQ(7)-发后即忘模型
- django 与 mysql 勾结指南
- mysql:字符串拼接
- Ms08067联合360漏洞响应平台(SRC)送给白帽子20本“精选的10本安全好书”
- 常用的内部网关协议(IGP)
- Android开发动态的监听网络状态的变化
- Jenkins端口号修改
- python 中/ 与 //的作用、用法
热门文章
- NPOI实现Word表格删除一行
- 高密集型工业体系步履蹒跚
- 怎样用html制作歌词字幕,pr歌词字幕制作方法
- VMware vCenter Server 7.0 U2b/6.7 U3n/6.5 U3p 修复高危安全漏洞
- 关键字查询输入%问题
- oracle数据库rtf内容替换,如何将RTF转换为纯文本?
- 二级Office知识点整合
- 计算机二级考试office考试技巧,2017年计算机二级考试Office应试技巧
- 计算机键盘重复设置,电脑键盘错乱怎么恢复 一键快速重新设置电脑快捷键方法...
- 如何刻录服务器安装系统光盘启动盘,如何刻录系统光盘