4.refelct.MethodByName()

3. 接口方法实现-MethodByName()方法

  1. 将动态类型压入栈,作为MethodByName。
  2. Type变量176偏移位置为MethodByName()方法地址。

样例代码

5   type person struct {
6       name string
7       age int32
8   }
20  var var_person person = person{name:"abc",age:18}
23  var var_type reflect.Type = reflect.TypeOf(var_person)
25  mymethod,b := var_type.MethodByName("Test_MethodByName1")

对应汇编

0x023d 00573 (reflect.go:25)    PCDATA  $2, $5
0x023d 00573 (reflect.go:25)    LEAQ    ""..autotmp_91+2744(SP), DI
0x0245 00581 (reflect.go:25)    XORPS   X0, X0
0x0248 00584 (reflect.go:25)    PCDATA  $2, $0
0x0248 00584 (reflect.go:25)    LEAQ    -48(DI), DI
0x024c 00588 (reflect.go:25)    DUFFZERO    $277
0x025f 00607 (reflect.go:25)    MOVQ    "".var_type+952(SP), AX
0x0267 00615 (reflect.go:25)    TESTB   AL, (AX)
0x0269 00617 (reflect.go:25)    MOVQ    176(AX), AX // 176 为MethodByName在Type接口方法中的偏移量
0x0270 00624 (reflect.go:25)    PCDATA  $2, $2
0x0270 00624 (reflect.go:25)    MOVQ    "".var_type+960(SP), CX //CX为动态类型person struct
0x0278 00632 (reflect.go:25)    PCDATA  $2, $0
0x0278 00632 (reflect.go:25)    MOVQ    CX, (SP)    //将Type接口变量值(即动态类型)压入栈
0x027c 00636 (reflect.go:25)    PCDATA  $2, $2
0x027c 00636 (reflect.go:25)    LEAQ    go.string."Test_MethodByName1"(SB), CX
0x0283 00643 (reflect.go:25)    PCDATA  $2, $0
0x0283 00643 (reflect.go:25)    MOVQ    CX, 8(SP)
0x0288 00648 (reflect.go:25)    MOVQ    $18, 16(SP)
0x0291 00657 (reflect.go:25)    CALL    AX  //调用方法 MethodByName(),具体实现见下文。
0x0293 00659 (reflect.go:25)    PCDATA  $2, $5
0x0293 00659 (reflect.go:25)    PCDATA  $0, $9
0x0293 00659 (reflect.go:25)    LEAQ    ""..autotmp_91+2744(SP), DI
0x029b 00667 (reflect.go:25)    PCDATA  $2, $6
0x029b 00667 (reflect.go:25)    LEAQ    24(SP), SI
0x02a0 00672 (reflect.go:25)    PCDATA  $2, $0
0x02a0 00672 (reflect.go:25)    DUFFCOPY    $826
0x02b3 00691 (reflect.go:25)    MOVBLZX 104(SP), AX
0x02b8 00696 (reflect.go:25)    MOVB    AL, ""..autotmp_92+115(SP)
0x02bc 00700 (reflect.go:25)    PCDATA  $2, $5
0x02bc 00700 (reflect.go:25)    PCDATA  $0, $10
0x02bc 00700 (reflect.go:25)    LEAQ    "".mymethod+2664(SP), DI
0x02c4 00708 (reflect.go:25)    PCDATA  $2, $6
0x02c4 00708 (reflect.go:25)    PCDATA  $0, $11
0x02c4 00708 (reflect.go:25)    LEAQ    ""..autotmp_91+2744(SP), SI
0x02cc 00716 (reflect.go:25)    PCDATA  $2, $0
0x02cc 00716 (reflect.go:25)    DUFFCOPY    $826
0x02df 00735 (reflect.go:25)    MOVBLZX ""..autotmp_92+115(SP), AX
0x02e4 00740 (reflect.go:25)    MOVB    AL, "".b+114(SP)

3.1 MethodByName()方法实现

//src\reflect\type.go

func (t *rtype) MethodByName(name string) (m Method, ok bool) {
	if t.Kind() == Interface {
		tt := (*interfaceType)(unsafe.Pointer(t))
		return tt.MethodByName(name)
	}
	ut := t.uncommon()
	if ut == nil {
		return Method{}, false
	}
	// TODO(mdempsky): Binary search.
	for i, p := range ut.exportedMethods() {
		if t.nameOff(p.name).name() == name {
			return t.Method(i), true
		}
	}
	return Method{}, false
}

3.2 如果动态类型本身就是一个接口

  1. 将变量转换为interfaceType类型。(iface变量第一个元素就是interfaceType类型)
  2. interfaceType.methods保存了接口所有方法。
  3. 根据方法名,找到对应方法。

3.2.1 interfaceType.MethodByName(name string)

  1. methods保存了接口的所有方法。
  2. 遍历methods找到匹配的方法.
// MethodByName method with the given name in the type's method set.
func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
	if t == nil {
		return
	}
	var p *imethod
	for i := range t.methods {
		p = &t.methods[i]
		if t.nameOff(p.name).name() == name {
			return t.Method(i), true
		}
	}
	return
}

3.2.2 interfaceType.nameOff()

  1. 根据interfaceType变量地址,由运行时找到对应的名字。
type nameOff int32 // offset to a name
type typeOff int32 // offset to an *rtype
type textOff int32 // offset from top of text section

type name struct {
	bytes *byte
}

func (t *rtype) nameOff(off nameOff) name {
	return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
}

// resolveNameOff resolves a name offset from a base pointer.
// The (*rtype).nameOff method is a convenience wrapper for this function.
// Implemented in the runtime package.
func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer

23  var var_type reflect.Type = reflect.TypeOf(var_person)
25  mymethod,b := var_type.MethodByName("Test_MethodByName1")

对应汇编

0x023d 00573 (reflect.go:25)    LEAQ    ""..autotmp_91+2744(SP), DI
0x0245 00581 (reflect.go:25)    XORPS   X0, X0
0x0248 00584 (reflect.go:25)    PCDATA  $2, $0
0x0248 00584 (reflect.go:25)    LEAQ    -48(DI), DI
0x024c 00588 (reflect.go:25)    DUFFZERO    $277
0x025f 00607 (reflect.go:25)    MOVQ    "".var_type+952(SP), AX
0x0267 00615 (reflect.go:25)    TESTB   AL, (AX)
0x0269 00617 (reflect.go:25)    MOVQ    176(AX), AX
0x0270 00624 (reflect.go:25)    PCDATA  $2, $2
0x0270 00624 (reflect.go:25)    MOVQ    "".var_type+960(SP), CX
0x0278 00632 (reflect.go:25)    PCDATA  $2, $0
0x0278 00632 (reflect.go:25)    MOVQ    CX, (SP)
0x027c 00636 (reflect.go:25)    PCDATA  $2, $2
0x027c 00636 (reflect.go:25)    LEAQ    go.string."Test_MethodByName1"(SB), CX
0x0283 00643 (reflect.go:25)    PCDATA  $2, $0
0x0283 00643 (reflect.go:25)    MOVQ    CX, 8(SP)
0x0288 00648 (reflect.go:25)    MOVQ    $18, 16(SP)
0x0291 00657 (reflect.go:25)    CALL    AX
0x0293 00659 (reflect.go:25)    PCDATA  $2, $5
0x0293 00659 (reflect.go:25)    PCDATA  $0, $9
0x0293 00659 (reflect.go:25)    LEAQ    ""..autotmp_91+2744(SP), DI
0x029b 00667 (reflect.go:25)    PCDATA  $2, $6
0x029b 00667 (reflect.go:25)    LEAQ    24(SP), SI
0x02a0 00672 (reflect.go:25)    PCDATA  $2, $0
0x02a0 00672 (reflect.go:25)    DUFFCOPY    $826
0x02b3 00691 (reflect.go:25)    MOVBLZX 104(SP), AX
0x02b8 00696 (reflect.go:25)    MOVB    AL, ""..autotmp_92+115(SP)
0x02bc 00700 (reflect.go:25)    PCDATA  $2, $5
0x02bc 00700 (reflect.go:25)    PCDATA  $0, $10
0x02bc 00700 (reflect.go:25)    LEAQ    "".mymethod+2664(SP), DI
0x02c4 00708 (reflect.go:25)    PCDATA  $2, $6
0x02c4 00708 (reflect.go:25)    PCDATA  $0, $11
0x02c4 00708 (reflect.go:25)    LEAQ    ""..autotmp_91+2744(SP), SI
0x02cc 00716 (reflect.go:25)    PCDATA  $2, $0
0x02cc 00716 (reflect.go:25)    DUFFCOPY    $826
0x02df 00735 (reflect.go:25)    MOVBLZX ""..autotmp_92+115(SP), AX
0x02e4 00740 (reflect.go:25)    MOVB    AL, "".b+114(SP)
tt := (*interfaceType)(unsafe.Pointer(t))
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.
}
  1. 调用 interfaceType.MethodByName()方法
    tt.MethodByName(name)
    interfaceType.methods保存了接口所有的方法。
//src\reflect\type.go
// imethod represents a method on an interface type
type imethod struct {
	name nameOff // name of method
	typ  typeOff // .(*FuncType) underneath
}

// interfaceType represents an interface type.
type interfaceType struct {
	rtype
	pkgPath name      // import path
	methods []imethod // sorted by hash
}

// src\runtime\type.go  与runtime变量名不同,结构完全一样
type interfacetype struct {
	typ     _type
	pkgpath name
	mhdr    []imethod
}

3.2.3 interfaceType.Method(i int) (m Method)

// Method returns the i'th method in the type's method set.
func (t *interfaceType) Method(i int) (m Method) {
	if i < 0 || i >= len(t.methods) {
		return
	}
	p := &t.methods[i]
	pname := t.nameOff(p.name)
	m.Name = pname.name()
	if !pname.isExported() {
		m.PkgPath = pname.pkgPath()
		if m.PkgPath == "" {
			m.PkgPath = t.pkgPath.name()
		}
	}
	m.Type = toType(t.typeOff(p.typ))
	m.Index = i
	return
}
  1. methods成员包含两个成员,name nameOff // name of methodtyp typeOff // .(*FuncType) underneath
  2. nameoff()函数,由运行时根据rtype变量地址,以及name偏移量计算出来。保存真正名字的位置。
  3. 如果名字一致,就返回该方法Method.
func (t *rtype) nameOff(off nameOff) name {
	return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
}

// resolveNameOff resolves a name offset from a base pointer.
// The (*rtype).nameOff method is a convenience wrapper for this function.
// Implemented in the runtime package.
func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
5   type person struct {
6         name string
7         age int32
8   }
21  var var_interface interface{} = person{name:"abc",age:18}
23  var var_type reflect.Type = reflect.TypeOf(var_interface)
     

对应汇编


0x00e0 00224 (reflect.go:23)    PCDATA  $2, $1
0x00e0 00224 (reflect.go:23)    MOVQ    "".var_interface+504(SP), AX
0x00e8 00232 (reflect.go:23)    PCDATA  $0, $1
0x00e8 00232 (reflect.go:23)    MOVQ    "".var_interface+496(SP), CX
0x00f0 00240 (reflect.go:23)    PCDATA  $0, $4
0x00f0 00240 (reflect.go:23)    MOVQ    CX, reflect.i+512(SP)   // 接口类型
0x00f8 00248 (reflect.go:23)    PCDATA  $2, $0
0x00f8 00248 (reflect.go:23)    MOVQ    AX, reflect.i+520(SP)   // 接口值
0x0100 00256 (reflect.go:23)    XORPS   X0, X0
0x0103 00259 (reflect.go:23)    MOVUPS  X0, "".~R0+352(SP)
0x010b 00267 (reflect.go:23)    XCHGL   AX, AX
0x010c 00268 (reflect.go:23)    XORPS   X0, X0
0x010f 00271 (reflect.go:23)    MOVUPS  X0, reflect.eface·3+672(SP)
// 对应源码 src\reflect\type.go
1374    func TypeOf(i interface{}) Type {
1375    	eface := *(*emptyInterface)(unsafe.Pointer(&i))
1376    	return toType(eface.typ)
1378    }

0x0117 00279 ($GOROOT/src/reflect/type.go:1375) PCDATA  $2, $1
0x0117 00279 ($GOROOT/src/reflect/type.go:1375) LEAQ    reflect.i+512(SP), AX
0x011f 00287 ($GOROOT/src/reflect/type.go:1375) PCDATA  $2, $0
0x011f 00287 ($GOROOT/src/reflect/type.go:1375) TESTB   AL, (AX)
0x0121 00289 ($GOROOT/src/reflect/type.go:1375) PCDATA  $2, $1
0x0121 00289 ($GOROOT/src/reflect/type.go:1375) MOVQ    reflect.i+520(SP), AX   //接口值
0x0129 00297 ($GOROOT/src/reflect/type.go:1375) PCDATA  $2, $3
0x0129 00297 ($GOROOT/src/reflect/type.go:1375) PCDATA  $0, $1
0x0129 00297 ($GOROOT/src/reflect/type.go:1375) MOVQ    reflect.i+512(SP), CX   //接口类型,eface.typ 即*rtype
0x0131 00305 ($GOROOT/src/reflect/type.go:1375) MOVQ    CX, reflect.eface·3+672(SP) //eface变量设置接口类型
0x0139 00313 ($GOROOT/src/reflect/type.go:1375) PCDATA  $2, $2
0x0139 00313 ($GOROOT/src/reflect/type.go:1375) MOVQ    AX, reflect.eface·3+680(SP) //eface变量设置接口值
0x0141 00321 ($GOROOT/src/reflect/type.go:1376) PCDATA  $2, $0
0x0141 00321 ($GOROOT/src/reflect/type.go:1376) PCDATA  $0, $5
0x0141 00321 ($GOROOT/src/reflect/type.go:1376) MOVQ    CX, reflect.t+128(SP)   //接口类型,首个元素
0x0149 00329 ($GOROOT/src/reflect/type.go:1376) XORPS   X0, X0
0x014c 00332 ($GOROOT/src/reflect/type.go:1376) MOVUPS  X0, "".~R0+448(SP)
0x0154 00340 ($GOROOT/src/reflect/type.go:1376) XCHGL   AX, AX

3003    func toType(t *rtype) Type {
3004    	if t == nil {
3005		    return nil
3006	    }
3007	    return t
3008    }

0x0155 00341 ($GOROOT/src/reflect/type.go:3004) CMPQ    reflect.t+128(SP), $0
0x015e 00350 (:0)       JNE     357
0x0160 00352 (:0)       JMP     3513
0x0165 00357 ($GOROOT/src/reflect/type.go:3007) PCDATA  $2, $1
0x0165 00357 ($GOROOT/src/reflect/type.go:3007) PCDATA  $0, $1
0x0165 00357 ($GOROOT/src/reflect/type.go:3007) MOVQ    reflect.t+128(SP), AX
0x016d 00365 ($GOROOT/src/reflect/type.go:3007) MOVQ    AX, ""..autotmp_45+216(SP)

0x0175 00373 ($GOROOT/src/reflect/type.go:1376) PCDATA  $2, $3
0x0175 00373 ($GOROOT/src/reflect/type.go:1376) LEAQ    go.itab.*reflect.rtype,reflect.Type(SB), CX //接口类型,即reflect.Type
0x017c 00380 ($GOROOT/src/reflect/type.go:1376) MOVQ    CX, ""..autotmp_48+1056(SP)
0x0184 00388 ($GOROOT/src/reflect/type.go:1376) MOVQ    AX, ""..autotmp_48+1064(SP)
0x018c 00396 ($GOROOT/src/reflect/type.go:1376) PCDATA  $2, $1
0x018c 00396 ($GOROOT/src/reflect/type.go:1376) PCDATA  $0, $6
0x018c 00396 ($GOROOT/src/reflect/type.go:1376) MOVQ    CX, "".~R0+448(SP)  //返回接口类型
0x0194 00404 ($GOROOT/src/reflect/type.go:1376) PCDATA  $2, $0
0x0194 00404 ($GOROOT/src/reflect/type.go:1376) MOVQ    AX, "".~R0+456(SP)  //返回接口值
0x019c 00412 ($GOROOT/src/reflect/type.go:1376) JMP     414
0x019e 00414 (reflect.go:23)    MOVQ    "".~R0+448(SP), AX
0x01a6 00422 (reflect.go:23)    PCDATA  $2, $2
0x01a6 00422 (reflect.go:23)    PCDATA  $0, $1
0x01a6 00422 (reflect.go:23)    MOVQ    "".~R0+456(SP), CX
0x01ae 00430 (reflect.go:23)    MOVQ    AX, ""..autotmp_49+1040(SP) //临时变量,接口类型
0x01b6 00438 (reflect.go:23)    MOVQ    CX, ""..autotmp_49+1048(SP) //临时变量,接口值
0x01be 00446 (reflect.go:23)    MOVQ    AX, "".~R0+352(SP)
0x01c6 00454 (reflect.go:23)    MOVQ    CX, "".~R0+360(SP)
0x01ce 00462 (reflect.go:23)    JMP     464
0x01d0 00464 (reflect.go:23)    PCDATA  $0, $7
0x01d0 00464 (reflect.go:23)    MOVQ    AX, "".var_type+480(SP) 
0x01d8 00472 (reflect.go:23)    PCDATA  $2, $0
0x01d8 00472 (reflect.go:23)    MOVQ    CX, "".var_type+488(SP)
fmt.Println("type:",reflect.TypeOf(var_type));
//输出:type: *reflect.rtype
20  var var_person person = person{name:"abc",age:18}
23  var var_type reflect.Type = reflect.TypeOf(var_person)
25  method,b := var_type.MethodByName("Test_MethodByName1")
27  numMethod := var_type.NumMethod()

25行调用MethodByName对应汇编

        0x023d 00573 (reflect.go:25)    PCDATA  $2, $5
        0x023d 00573 (reflect.go:25)    LEAQ    ""..autotmp_79+2416(SP), DI
        0x0245 00581 (reflect.go:25)    XORPS   X0, X0
        0x0248 00584 (reflect.go:25)    PCDATA  $2, $0
        0x0248 00584 (reflect.go:25)    LEAQ    -48(DI), DI
        0x024c 00588 (reflect.go:25)    DUFFZERO        $277
        0x025f 00607 (reflect.go:25)    MOVQ    "".var_type+840(SP), AX
        0x0267 00615 (reflect.go:25)    TESTB   AL, (AX)
        
        0x0269 00617 (reflect.go:25)    MOVQ    176(AX), AX  // 将MethodByName方法地址放入 AX,var_type变量向后偏移176位置
                                                             //见下方 go.itab.*reflect.rtype,reflect.Type SRODATA dupok size=272
                                                             // rel 176+8 t=1 reflect.(*rtype).MethodByName+0
                                                        
        0x0270 00624 (reflect.go:25)    PCDATA  $2, $2
        0x0270 00624 (reflect.go:25)    MOVQ    "".var_type+848(SP), CX
        0x0278 00632 (reflect.go:25)    PCDATA  $2, $0
        0x0278 00632 (reflect.go:25)    MOVQ    CX, (SP)
        0x027c 00636 (reflect.go:25)    PCDATA  $2, $2
        0x027c 00636 (reflect.go:25)    LEAQ    go.string."Test_MethodByName1"(SB), CX
        0x0283 00643 (reflect.go:25)    PCDATA  $2, $0
        0x0283 00643 (reflect.go:25)    MOVQ    CX, 8(SP)
        0x0288 00648 (reflect.go:25)    MOVQ    $18, 16(SP)
        0x0291 00657 (reflect.go:25)    CALL    AX      // 调用MethodByName方法
        0x0293 00659 (reflect.go:25)    PCDATA  $2, $5
        0x0293 00659 (reflect.go:25)    PCDATA  $0, $9
        0x0293 00659 (reflect.go:25)    LEAQ    ""..autotmp_79+2416(SP), DI
        0x029b 00667 (reflect.go:25)    PCDATA  $2, $6
        0x029b 00667 (reflect.go:25)    LEAQ    24(SP), SI
        0x02a0 00672 (reflect.go:25)    PCDATA  $2, $0
        0x02a0 00672 (reflect.go:25)    DUFFCOPY        $826
        0x02b3 00691 (reflect.go:25)    MOVBLZX 104(SP), AX
        0x02b8 00696 (reflect.go:25)    MOVB    AL, ""..autotmp_80+115(SP)
        0x02bc 00700 (reflect.go:25)    PCDATA  $2, $5
        0x02bc 00700 (reflect.go:25)    PCDATA  $0, $10
        0x02bc 00700 (reflect.go:25)    LEAQ    "".method+2336(SP), DI
        0x02c4 00708 (reflect.go:25)    PCDATA  $2, $6
        0x02c4 00708 (reflect.go:25)    PCDATA  $0, $11
        0x02c4 00708 (reflect.go:25)    LEAQ    ""..autotmp_79+2416(SP), SI
        0x02cc 00716 (reflect.go:25)    PCDATA  $2, $0
        0x02cc 00716 (reflect.go:25)    DUFFCOPY        $826
        0x02df 00735 (reflect.go:25)    MOVBLZX ""..autotmp_80+115(SP), AX
        0x02e4 00740 (reflect.go:25)    MOVB    AL, "".b+114(SP)
//src\runtime\runtime2.go
type itab struct {
	inter *interfacetype    //8 字节
	_type *_type            //8 字节
	hash  uint32   //4 字节 copy of _type.hash. Used for type switches.
	_     [4]byte   //4 字节
	fun   [1]uintptr // 8 字节variable sized. fun[0]==0 means _type does not implement inter.
}
go.itab.*reflect.rtype,reflect.Type SRODATA dupok size=272
        0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        0x0010 d6 c9 33 e3 00 00 00 00 00 00 00 00 00 00 00 00  ..3.............
        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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        0x0050 00 00 00 00 00 00 00 00 00 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 00 00 00 00 00 00 00 00  ................
        0x0090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        0x00a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        0x00b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        0x00c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        0x00d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        0x00e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        0x00f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        0x0100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        rel 0+8 t=1 type.reflect.Type+0     // itab.inter 接口类型
        rel 8+8 t=1 type.*reflect.rtype+0   // itab._type 动态类型,即reflect.rtype
        rel 24+8 t=1 reflect.(*rtype).Align+0   //itab.fun
        rel 32+8 t=1 reflect.(*rtype).AssignableTo+0
        rel 40+8 t=1 reflect.(*rtype).Bits+0
        rel 48+8 t=1 reflect.(*rtype).ChanDir+0
        rel 56+8 t=1 reflect.(*rtype).Comparable+0
        rel 64+8 t=1 reflect.(*rtype).ConvertibleTo+0
        rel 72+8 t=1 reflect.(*rtype).Elem+0
        rel 80+8 t=1 reflect.(*rtype).Field+0
        rel 88+8 t=1 reflect.(*rtype).FieldAlign+0
        rel 96+8 t=1 reflect.(*rtype).FieldByIndex+0
        rel 104+8 t=1 reflect.(*rtype).FieldByName+0
        rel 112+8 t=1 reflect.(*rtype).FieldByNameFunc+0
        rel 120+8 t=1 reflect.(*rtype).Implements+0
        rel 128+8 t=1 reflect.(*rtype).In+0
        rel 136+8 t=1 reflect.(*rtype).IsVariadic+0
        rel 144+8 t=1 reflect.(*rtype).Key+0
        rel 152+8 t=1 reflect.(*rtype).Kind+0
        rel 160+8 t=1 reflect.(*rtype).Len+0
        rel 168+8 t=1 reflect.(*rtype).Method+0
        rel 176+8 t=1 reflect.(*rtype).MethodByName+0   //偏移176位置为MethodByName方法地址
        rel 184+8 t=1 reflect.(*rtype).Name+0
        rel 192+8 t=1 reflect.(*rtype).NumField+0
        rel 200+8 t=1 reflect.(*rtype).NumIn+0
        rel 208+8 t=1 reflect.(*rtype).NumMethod+0  //偏移208位置为NumMethod方法地址
        rel 216+8 t=1 reflect.(*rtype).NumOut+0
        rel 224+8 t=1 reflect.(*rtype).Out+0
        rel 232+8 t=1 reflect.(*rtype).PkgPath+0
        rel 240+8 t=1 reflect.(*rtype).Size+0
        rel 248+8 t=1 reflect.(*rtype).String+0
        rel 256+8 t=1 reflect.(*rtype).common+0
        rel 264+8 t=1 reflect.(*rtype).uncommon+0

3.2. 不是接口变量,转换为uncommonType类型

  1. 根据变量的实际类型

// uncommonType is present only for defined types or types with methods
// (if T is a defined type, the uncommonTypes for T and *T have methods).
// Using a pointer to this struct reduces the overall size required
// to describe a non-defined type with no methods.
type uncommonType struct {
	pkgPath nameOff // import path; empty for built-in types like int, string
	mcount  uint16  // number of methods
	xcount  uint16  // number of exported methods
	moff    uint32  // offset from this uncommontype to [mcount]method
	_       uint32  // unused
}


func (t *rtype) uncommon() *uncommonType {
	if t.tflag&tflagUncommon == 0 {
		return nil
	}
	switch t.Kind() {
	case Struct:
		return &(*structTypeUncommon)(unsafe.Pointer(t)).u
	case Ptr:
		type u struct {
			ptrType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Func:
		type u struct {
			funcType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Slice:
		type u struct {
			sliceType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Array:
		type u struct {
			arrayType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Chan:
		type u struct {
			chanType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Map:
		type u struct {
			mapType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Interface:
		type u struct {
			interfaceType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	default:
		type u struct {
			rtype
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	}
}

你可能感兴趣的:(Go,Go,Reflect)