golang类型基本是由内置类型和自定义类型组成。本节会围绕内置类型和自定义类型来讲解其二者的异同。
什么是内置类型
所谓内置类型,是在golang源码中本身一开始定义的一系列类型,基本包括:
int8
int16
int64
int32
int
byte
func
map
等。
什么是自定义类型
自定义类型是在用户进程中自定义的类型,具体如下:
type T int
type S struct{
Name string
}
这里 T、S 就是自定义类型,自定义类型有个最大的不同就是,可以基于自定义类型进行函数方法定义。
比如:
func (t T) TFunc(){
}
func (s S) SFunc(){
}
可以在自定义类型上关联函数。
内置类型元数据
类型元数据是内置类型和自定义类型的描述信息。
比如通过某个类型的类型元数据我们可以知道:
类型名称
类型大小
对齐边界
是否自定义
等…
而对应的类型元数据结构体:
type _type struct {
size uintptr
ptrdata uintptr // size of memory prefix holding all pointers
hash uint32
tflag tflag
align uint8
fieldAlign uint8
kind uint8
// function for comparing objects of this type
// (ptr to object A, ptr to object B) -> ==?
equal func(unsafe.Pointer, unsafe.Pointer) bool
// gcdata stores the GC type data for the garbage collector.
// If the KindGCProg bit is set in kind, gcdata is a GC program.
// Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
gcdata *byte
str nameOff
ptrToThis typeOff
}
当然通过扩展引申,可以看到除了_type之外,还有slicetype,chantype等等。他们结构中必然要有_type作为成员变量,比如slicetype
type slicetype struct {
typ _type
elem *_type
}
上述slicetype类型表示,slice类型元数据有两个成员变量,elem和typ。
其中elem,是指向其存储元素的类型元数据。比如,如果是[]string,
那么typ表示[]string整体的类型信息(类型名称、类型大小、对齐边界…)
而elem则表示string的类型元数据信息(string的类型名称、string的类型大小和对齐边界)
自定义类型元数据
如果是自定义类型,那么除了基本的_type表示的类型元数据外,还会又个结构体即: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 方法元数据数组的偏移值(方法元数据组成的数组相对于这个uncommontype结构体偏移了多少字节)
_ uint32 // unused
}
举例:
type T int
func (t T) TFunc(){
}
那么对于自定义类型T来说其由两部分组成
_type(自定义类型T对应的内置类型int的类型元数据) |
---|
uncommontype(自定义类型T的专属的信息,比如T有关联方法TFunc,那么对应moff的值就是T的方法偏移量) |
再举个例子:
type testArr []string
那么自定义类型testArr则是由内置类型[]string的类型元数据sliceType和uncommontype组成。
问题:上述说道自定义类型关联的方法,是如何根据偏移量找到对应函数的。
首先我们知道uncommontype.moff是表示自定义类型的方法偏移量的。
系统函数调用的时候会根据uncommontype的地址偏移moff个位置,就会找到对应的方法。
关于自定义类型和别名
type MyType1=int32 //别名 ,MyType1会关联到同一个类型元数据
type MyType2 int32 //自定义类型,两个是不一样的,int32对应的类型元数据就是个简单的_type结构体信息。 而MyType2对应的是_type和uncommontype的组合
也就是说MyType1的类型元数据和int32是一样的。
总结
本节主要讲了自定义类型和内置类型,其根本的数据结构,以及他们的区别。
1、golang中类型主要分为内置类型和自定义类型;
2、_type是类型元数据的信息表达;
3、一些特殊的内置类型可能需要不止一个_type来表达,比如slicetype;
4、自定义类型组成:内置类型元数据、uncommontype;
5、自定义类型的uncommontype中存储的是自定义类型专属的信息,比如函数偏移值;
6、通过上述可以知道自定义类型是可以关联func从而可以实现类似成员函数的调用。这也是为什么内置类型不能这么用的原因;
7、类型别名和自定义类型是不一样的,类型别名其实对应的类型元数据是和其起别名的类型的内置类型抑制的;