2.reflect.TypeOf()

栏目: Go · 发布时间: 6年前

内容简介:反射主要与Golang的interface类型相关(它的type是concrete type),只有interface类型才有反射一说。反射就是用来检测存储在接口变量内部(值value;类型concrete type) pair对的一种机制。它提供了两种类型(或者说两个方法)让我们可以很容易的访问接口变量内容,分别是

反射主要与Golang的interface类型相关(它的type是concrete type),只有interface类型才有反射一说。

反射就是用来检测存储在接口变量内部(值value;类型concrete type) pair对的一种机制。

Golang的reflect有什么样的方式可以直接获取到变量内部的信息?

它提供了两种类型(或者说两个方法)让我们可以很容易的访问接口变量内容,分别是 reflect.TypeOf()reflect.ValueOf()

1. reflect.TypeOf(i interface{}) Type

// 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)) // 将入参iface的接口类型。赋值为eface的动态类型。
    return toType(eface.typ)    //将eface的动态类型,设置为Type接口的值。
}

1.1 TypeOf()返回内容

由于 TypeOf() 入参为空接口。在将一个接口传递给TypeOf时,可能会发生类型转换。

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

总结:

1. TypeOf返回入一个Type接口类型。

2. Type接口的值为入参的动态类型。

3. TypeOf不关心入参的值。

type iface struct {
    tab  *itab
    data unsafe.Pointer
}
type itab struct {
    inter *interfacetype
    _type *_type
    hash  uint32 // copy of _type.hash. Used for type switches.
    _     [4]byte
    fun   [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}
type interfacetype struct {
    typ     _type
    pkgpath name
    mhdr    []imethod
}
// reflect.emptyInterface == runtime.eface
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
    typ  *rtype
    word unsafe.Pointer
}
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

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入栈 **
    //  将入参强制转换为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
    // 将入参转换后的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   // 
0x0174 00372 ($GOROOT/src/reflect/type.go:1375) PCDATA  $2, $0
0x0174 00372 ($GOROOT/src/reflect/type.go:1375) TESTB   AL, (AX)        
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   // 变量值到 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   // 动态类型person 到CX
0x0186 00390 ($GOROOT/src/reflect/type.go:1375) MOVQ    CX, reflect.eface·3+1144(SP)    
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)

        // 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)   // 将动态类型设置给临时变量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   // 判断是否空类型
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   // 将动态类型设置到AX
0x01c2 00450 ($GOROOT/src/reflect/type.go:3007) MOVQ    AX, ""..autotmp_78+280(SP)
0x01ca 00458 ($GOROOT/src/reflect/type.go:1376) PCDATA  $2, $4
        // 临时变量autotmp_84 即Type类型接口变量  
0x01ca 00458 ($GOROOT/src/reflect/type.go:1376) LEAQ    go.itab.*reflect.rtype,reflect.Type(SB), CX //设置返回值接口类型为Type
0x01d1 00465 ($GOROOT/src/reflect/type.go:1376) MOVQ    CX, ""..autotmp_84+1288(SP) 
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)
// toType converts from a *rtype to a Type that can be returned
// to the client of package reflect. In gc, the only concern is that
// a nil *rtype must be replaced by a nil Type, but in gccgo this
// function takes care of ensuring that multiple *rtype for the same
// type are coalesced into a single Type.
func toType(t *rtype) Type {
    if t == nil {
        return nil
    }
    return t
}

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 pointers
    hash       uint32   // 4 字节 hash of type; avoids computation in hash tables
    tflag      tflag    // 1 字节 extra type information flags
    align      uint8    // 1 字节 alignment of variable with this type
    fieldAlign uint8    // 1 字节 alignment of struct field with this type
    kind       uint8    // 1 字节 enumeration for C
    alg        *typeAlg // 8 字节 algorithm table
    gcdata     *byte    // 8 字节 garbage collection data
    str        nameOff  // 4 字节 string form
    ptrToThis  typeOff  // 4 字节 type for pointer to this type, may be zero
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Algorithms

Algorithms

Sanjoy Dasgupta、Christos H. Papadimitriou、Umesh Vazirani / McGraw-Hill Education / 2006-10-16 / GBP 30.99

This text, extensively class-tested over a decade at UC Berkeley and UC San Diego, explains the fundamentals of algorithms in a story line that makes the material enjoyable and easy to digest. Emphasi......一起来看看 《Algorithms》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具