2.reflect.TypeOf()

2024-02-29 02:08
文章标签 reflect typeof

本文主要是介绍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时,可能会发生类型转换。

  1. i不是空接口,即iface对象。会产生convI2E转换,将iface的动态类型赋值为eface动态类型。
  2. i本身就是空接口。直接赋值。
  3. eface.typ即入参的动态类型转换为Type接口类型。(接口类型为Type,值为eface.typ

3 总结

  1. TypeOf返回入一个iface变量。
  2. iface.tabreflect.Type接口类型。
  3. iface.data为入参的动态类型
  4. 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()的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/757276

相关文章

ES6基础----Reflect的使用

目录   Reflect 是 ES6 提出的针对对象操作的 API,目的是为了让对象的操作变为函数式,更加统一规范,后续新增的对象方法将放在 Reflect 1、 向对象中添加属性及内容     --添加和重名修改 2、得到对象的属性及内容 3、删除对象的属性及内容    --返回布尔值 4、判断对象的属性是否存在   ---返回布尔值   Reflect 是 ES6 提出的针

Go游戏服务器开发的一些思考(三十九):go reflect的正确使用方法

错误的使用 go reflect包,在写一些通用库、通用模块时,提供了不少便利。 但是需要注意,go reflect包是非常慢的! 下图,就是一次失败使用go reflect包的尝试: (CStructGO 是 本人使用go reflect包写的一个C-Style Struct协议库:cstruct-go) 可以看到,同样的功能,cstruct-go比protobuf慢了一个数量级。

Golang利用reflect包实现struct相互填充

最近在用Golang写一些简单的业务,经常需要在两类相似的结构体之间相互填充数据,如果struct只有少数几个field,相互赋值还好;但如果struct有很多field的话,简直吐血,代码也不雅观,对于懒癌晚期简直不能容忍,看了下Golang的reflect包,好像找到一种偷懒的办法。。。 type Request struct {Field1 stringField2 stringFiel

C++ forbids declaration of ‘typeof’ with no type

这个错误有点闹心,因为 C++11 把 关键字typeof改为decltype了。 怎么做好两者的兼容性呢,只能使用 if 宏判断来做,比如我的代码: #if __cplusplus >= 201103L#define container_of(ptr, type, member) ({ \const decltype(((type *)0)->member)*__mptr

__typeof在Xcode7中的使用

前段时间做的时候就遇到了这个问题,今天把它记录下来。就是之前的代码明明没有问题可是应用到xcode7.3和ios9.3以后就出现了错误提示。 如下代码:这个是类库中的一段代码,在之前是没有问题的,但是用到新的环境中竟然报错 __weak typeof(self) weakSelf = self; _FDViewControllerWillAppearInjectBlock block = ^

es6(基础十六) Reflect

一、设计目的     1.以后方法只部署在Reflect对象身上    2.修改某些Object方法的返回结果    3.统一标准     之前有啥:delete obj[key]     key in obj等     统一改成 Reflect.has()     Reflect.deleteProperty(obj,name)     4.方便 //读取let obj = {nam

java.lang.reflect.Type是什么

Java 中的 java.lang.reflect.Type 在 Java 中,java.lang.reflect.Type 是一个接口,代表所有类型的通用超类型。它包括原始类型、参数化类型、数组类型、类型变量和基本类型。在反射机制中,Type 接口用于提供对 Java 类型系统的抽象表示,使得在运行时能够对类型进行更深入的检查和操作。 实现 java.lang.reflect.Type 有

java中的java.lang.reflect.Type在Spring框架中的用处

背景介绍 Type在java中表示类型,包括了 Class: ParametedType: List WildType: 如 ArrayType: 如T[] TypeVariable: 如T 解决一个实际问题 需求:假设我们有一个Repository接口,有2个实现类Repository和Repository2个bean,但是我们只想用到其中的一个bean,如personRepository

Golang gccgo编译报错 undefined reference to `reflect.unsafe_New‘的解决办法

根据github.com/modern-go/reflect2/issues/21所述,这是由于gccgo 11出于某些原因将reflect.unsafe_New重命名为reflect.unsafe__New所致,因此只需要更改$GOHOME/pkg/mod/github.com/modern-go/reflect2@vx.x.x-xxxx/unsafe_link.go如下 packa

java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType

今天在整合ssh框架时,用的全注解性,把Service和Dao都抽取了一个BaseService和BaseDao,在执行删除语句是出现了 java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType  或   Unknown entity: java.lang.Object,查网上资料和不断查看代码,后面发现是在Bas