Open Lehirt opened 1 year ago
内置类型元数据:
type slicetype struct {
typ _type
elem *_type
}
type ptrtype struct {
typ _type
elem *_type
}
type maptype struct {
typ _type
key *_type
elem *_type
bucket *_type // internal type representing a hash bucket
// function for hashing keys (ptr to key, seed) -> hash
hasher func(unsafe.Pointer, uintptr) uintptr
keysize uint8 // size of key slot
elemsize uint8 // size of elem slot
bucketsize uint16 // size of bucket
flags uint32
}
...
自定义类型元数据,还会存在 uncommontype 结构:
type uncommontype struct {
pkgpath nameOff
mcount uint16 // number of methods
xcount uint16 // number of exported methods
moff uint32 // offset from this uncommontype to [mcount]method
}
方法元数据:
type method struct {
name nameOff
mtyp typeOff
ifn textOff
tfn textOff
}
空接口 interface{}
type eface struct {
_type *_type
data unsafe.Pointer
}
非空接口:
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
}
itab 可以从 _type 中获取到变量类型元数据的方法元数据,并从 fun 中获取到。
类型断言
// 1. 空接口.(具体类型) :e.(*os.File)是要判断e存储的_type是否指向*os.File的类型元数据。
var e interface{}
//......
r,ok := e.(*os.File)
// 2. 非空接口.(具体类型) :rw.(*os.File)是要判断rw的动态类型是否为*os.File。
var rw io.ReadWriter
//......
r,ok := rw.(*os.File)
// 3. 空接口.(非空接口):e.(io.ReadWriter)是判断e的动态类型是否实现了io.ReadWriter接口。
var e interface{}
//......
rw,ok := e.(io.ReadWriter)
// 4. 非空接口.(非空接口):w.(io.ReadWriter)是要判断w的动态类型是否实现了io.ReadWriter接口。
var w io.Writer
//......
rw,ok := w.(io.ReadWriter)
如何判断动态类型_type是否实现了xxx接口? 使用 <接口,动态类型> 的 itab 缓存判断,若缓存不存在,则使用动态类型的方法列表匹配接口的方法列表并更新缓存。
反射:获取类型的元数据(字段、方法etc.)
reflect 包中存在一套与 runtime 相同的类型struct
反射核心类型:reflect.Type
和 reflect.Value
type Type interface {
Align() int //对齐边界
FieldAlign() int //作为结构体字段的对齐边界
Method(int) Method //获取方法数组中第i个Method
MethodByName(string) (Method, bool) //按照名称查找方法
NumMethod() int //方法列表中可导出方法的数目
Name() string //类型名称
PkgPath() string //包路径
Size() uintptr //该类型变量占用字节数
String() string //获取类型的字符串表示
Kind() Kind //类型对应的reflect.Kind
Implements(u Type) bool //该类型是否实现了接口u
AssignableTo(u Type) bool //是否可以赋值给类型u
ConvertibleTo(u Type) bool //是否可转换为类型u
Comparable() bool //是否可比较
//只能应用于某些Kind的方法
//Int*, Uint*, Float*, Complex*:
Bits() int
//Array,Ptr,Slice,Map:
Elem() Type
//Array
Len() int
//Chan:ChanDir, Elem
ChanDir() ChanDir
//Func:
In(i int) Type
NumIn() int
Out(i int) Type
NumOut() int
IsVariadic() bool
//Map:
Key() Type
//Struct:
Field(i int) StructField
FieldByIndex(index []int) StructField
FieldByName(name string) (StructField, bool)
FieldByNameFunc(match func(string) bool) (StructField, bool)
NumField() int
common() *rtype
uncommon() *uncommonType
}
使用 reflect.TypeOf
可以获取到传入参数的 reflect.Type
结构体。
func TypeOf(i interface{}) Type {
eface := *(*emptyInterface)(unsafe.Pointer(&i))
return toType(eface.typ)
}
调用reflect.TypeOf(a)时参数a存在以下转换:a -> interface{} -> reflect.emptyInterface -> reflect.Type 。重点是要理解反射如何拿到反射变量的类型元数据。
类型元数据 runtime._type :