3. 接口方法实现-MethodByName()方法
- 将动态类型压入栈,作为MethodByName。
- Type变量176偏移位置为MethodByName()方法地址。
0x01ba 00442 ($GOROOT/src/reflect/type.go:3007) MOVQ reflect.t+224(SP), AX
0x01c2 00450 ($GOROOT/src/reflect/type.go:3007) MOVQ AX, ""..autotmp_90+280(SP)
0x01ca 00458 ($GOROOT/src/reflect/type.go:1376) PCDATA $2, $4
0x01ca 00458 ($GOROOT/src/reflect/type.go:1376) LEAQ go.itab.*reflect.rtype,reflect.Type(SB), CX
0x01d1 00465 ($GOROOT/src/reflect/type.go:1376) MOVQ CX, ""..autotmp_97+1384(SP)
0x01d9 00473 ($GOROOT/src/reflect/type.go:1376) MOVQ AX, ""..autotmp_97+1392(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+792(SP)
0x01e9 00489 ($GOROOT/src/reflect/type.go:1376) PCDATA $2, $0
0x01e9 00489 ($GOROOT/src/reflect/type.go:1376) MOVQ AX, "".~R0+800(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+800(SP), AX
0x01fb 00507 (reflect.go:23) PCDATA $0, $3
0x01fb 00507 (reflect.go:23) MOVQ "".~R0+792(SP), CX
0x0203 00515 (reflect.go:23) MOVQ CX, ""..autotmp_98+1368(SP)
0x020b 00523 (reflect.go:23) MOVQ AX, ""..autotmp_98+1376(SP)
0x0213 00531 (reflect.go:23) MOVQ CX, "".~R0+776(SP)
0x021b 00539 (reflect.go:23) MOVQ AX, "".~R0+784(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+952(SP)
0x022d 00557 (reflect.go:23) PCDATA $2, $0
0x022d 00557 (reflect.go:23) MOVQ AX, "".var_type+960(SP)
0x0235 00565 (reflect.go:24) MOVL $3000, "".var_int32+116(SP)
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 //Type接口变量
0x0267 00615 (reflect.go:25) TESTB AL, (AX)
0x0269 00617 (reflect.go:25) MOVQ 176(AX), AX //MethodByName函数偏移量176
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 //调用 MethodByName 方法
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 如果动态类型本身就是一个接口
- 将变量转换为interfaceType类型。(iface变量第一个元素就是interfaceType类型)
- interfaceType.methods保存了接口所有方法。
- 根据方法名,找到对应方法。
3.2.1 interfaceType.MethodByName(name string)
- methods保存了接口的所有方法。
- 遍历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()
- 根据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.
}
- 调用 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
}
-
methods
成员包含两个成员,name nameOff // name of method
和typ typeOff // .(*FuncType) underneath
- nameoff()函数,由运行时根据rtype变量地址,以及name偏移量计算出来。保存真正名字的位置。
- 如果名字一致,就返回该方法
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类型
- 根据变量的实际类型
// 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
}
}