方法本质就是函数,只不过调用时接受会作为第一个参数传入
问题:编译阶段能知道类型,但是在执行阶段如何知道
built-in
- int8
- int16
- int32
- int64
- int
- byte
- string
- slice
- func
- map
- …
自定义类型
type T int
type T struct { name string }
type T interface { Name() string }
类型系统 #
类型元数据 #
runtime._type
- 类型名称
- 类型大小
- 对齐边界
- 是否自定义
- …
type _type struct {
	size          uintptr
	ptrdata       uintptr
	hash          uint32
	tflag         tflag
	align         uint8
	fieldAlign    uint8
	kind          uint8
	equal         func(unsafe.Pointer, unsafe.Pointer) bool
	gcdata        *byte
	str           nameOff
	ptrToThis     typeOff
}type slicetype struct {
  typ _type
  elem *_type ----> stringtype
}- int64 int64type
- …
如果是自定义类型:
type uncommontype struct {
  pkgpath nameOff // 包路径
  mcount uint16 // 方法数目
  moff uint32 // 方法元数据数组的偏移值
}
// 方法描述信息
type method struct {
  name nameOff
  mtyp typeOff
  ifn textOff
  tfn textOff
}例如基于 []string 定义 myslice
type myslice []string
func (ms myslice) Len() {
  fmt.Println(len(ms))
}
func (ms myslice) Cap() {
  fmt.Println(cap(ms))
}myslice 类型元数据
- slicetype
- uncommontype
区别 #
- type MyType1 = int32别名- MyType1 和 int32 都会关联到 int32 类型元数据
 
- type MyType2 = int32自定义类型- int32 指向 int32 类型元数据
- MyType2 指向 MyType2 类型元数据
 
空接口 interface{} #
type eface struct {
	_type *_type // 动态类型元数据
	data  unsafe.Pointer // 动态值
}- var e interface{}- _type = nil
- data = nil
 
- f, _ := os.Open("xxx.txt")- *os.File 类型元数据 _type ... uncommontype
- e = f- _type = *os.File 类型元数据
- data = f
 
非空接口 #
type iface struct {
	tab  *itab
	data unsafe.Pointer
}// layout of Itab known to compilers
// allocated in non-garbage-collected memory
// Needs to be in sync with
// ../cmd/compile/internal/reflectdata/reflect.go:/^func.WriteTabs.
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 方法列表
}- var rw io.ReadWriter- tab = nil
- data = nil
 
- f, _ := os.Open("xxx.txt")
- rw = f- data = f
 

itab 缓存 #
itab 中的 inter 和 _type 确定了 itab 就不会改变了 所
key <接口类型,动态类型>

// Note: change the formula in the mallocgc call in itabAdd if you change these fields.
type itabTableType struct {
	size    uintptr             // length of entries array. Always a power of 2.
	count   uintptr             // current number of filled entries.
	entries [itabInitSize]*itab // really [size] large
}
func itabHashFunc(inter *interfacetype, typ *_type) uintptr {
	// compiler has provided some good hash codes for us.
	return uintptr(inter.Type.Hash ^ typ.Hash)
}类型断言 #
https://www.bilibili.com/video/BV1iZ4y1T7zF?p=3&vd_source=ddc8289a36a2bf501f48ca984dc0b3c1