defer:是go语言的一个关键字,用来修饰函数,其作用是让defer后面跟的函数或者方法调用能够延迟到当前所在函数return或者panic的时候再执行。
- groutine结构体里有_defer链表指针的link字段,defer语句会创建_defer结构体,依次创建的_defer结构体以头插法插入_defer链表中(fifo)
- go编译过程:(语法分析)生成语法树—>(语法优化,逃逸分析,内敛优化)生成抽象语法树—>(defer等关键字处理)SSA中间代码—>可执行代码
- _defer内存分配
- 堆上分配:deferproc()会内存复用,优先在本地和全局_defer缓存池找到可用存储,找不到新建堆存储
- 栈上分配:逃逸分析确定_defer在栈上后,编译器自动初始化栈上 _defer,并传参给deferprocStack()
- 开放编码:defer不在循环内且defer较少则内联优化末尾直接调用defer函数,减少函数调用开销。
- return执行时触发call回调deferreturn(),遍历_defer链表依次执行_ _defer结构体内函数
interface:一组方法方法的声明,任何对象实现其全部方法就是实现其接口
- 空接口:可以接收任何类型数据。底层eface有_type动态类型元数据和data动态值(指针)
- 非空接口:底层iface,iface的字段data存储动态值,iface的字段tab指向itab结构体,itab的inter字段指向interfacetype结构体,itab的_type字段指向动态类型的元数据,interfacetype的mhdr字段是存储方法列表的数组,数组内容赋值过程会拷贝到itab的fun数组中
- itab缓存:采用itabTable结构缓存同类型itab,具体存储在itabTable的entries字段里,entries是hash表,key是接口类型与是积累性分别哈希后的异或值。hash冲突采用开放地址法,其次可能会二次寻址法