string

c语言string,本质上char数组,结尾用\0作为分割符。所以string实际元素,不可以包含\0。
go语言string,本质上是struct,结构如下,首元素地址+长度。所以go可以包含\0作为元素。
type stringStruct struct {
    str unsafe.Pointer
    len int
}

slice

go语言slice,是数组结构的再封装,支持扩容。结构如下
type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

在go语言实际开发中,array作为函数参数值传递,而slice是引用传递。底层数组不变。
且通过数组实例切片的时候,引用的底层数组就是此数组。修改值的时候要当心

slice扩容规则:
    1,预估扩容
        所需容量大于当前容量的二倍,预估值则为所需容量
        所需容量小于当前容量的二倍,且待扩容总数小于1024,直接翻倍
        所需容量小于当前容量的二倍,且待扩容总数大于1024,按照1/4扩容

    2,内存对其
        拿到预估容量,需要考虑内存对齐,需要根据元素大小,和预估容量计算出所占用的
        字节数,然后通过字节数向上取最接近的字节数。
        通过最接近的字节数,拿到真实的预估容量。

struct

结构体,理解成可以封装不同数据结构的一个总的数据结构,属于自定义数据结构
结构体指针指向首元素地址

结构体要考虑内存对其。根据计算机32位,64位的不同,内存对齐的规则不同。
反正内存对其的核心就是减少cpu通过地址总线加载数据的次数。能一次加载到就不加载多次。
虽然有时候会造成内存的浪费。

map

map结构,底层一般是hash表实现。
常见hash函数
    1,取模   hash%m
    2,位与运算 hash & (m-1)   m必须是2的整数次幂
hash冲突解决方法:
    1,拉链法
    2,开放地址法

hash表扩容
    1,hash负载因子,判断是否需要扩容
        count/m

    2,渐进式扩容
        当判断hash表需要扩容,则分配足够多的空间,且并不是直接copy旧空间的数据到新空间
        因为这样可能会带来瞬时性能抖动。

        渐进式扩容,就是标记当前hash表为需要扩容状态,并且记录新老地址以及扩容的偏移量。
        在后续每次hash表操作时,迁移部分数据到新地址。多次操作过程中,完成扩容。修改
        hash表状态位非扩容装填。扩容完成。

go语言map
    本质上,go语言map是一个做过高级封装的hash表
    // A header for a Go map.
    type hmap struct {
        // Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
        // Make sure this stays in sync with the compiler's definition.
        count     int // # live cells == size of map.  Must be first (used by len() builtin)
        flags     uint8
        B         uint8  // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
        noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
        hash0     uint32 // hash seed
        buckets    unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
        oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
        nevacuate  uintptr        // progress counter for evacuation (buckets less than this have been evacuated)

        extra *mapextra // optional fields
    }

溢出桶
    // mapextra holds fields that are not present on all maps.
    type mapextra struct {
        // If both key and elem do not contain pointers and are inline, then we mark bucket
        // type as containing no pointers. This avoids scanning such maps.
        // However, bmap.overflow is a pointer. In order to keep overflow buckets
        // alive, we store pointers to all overflow buckets in hmap.extra.overflow and hmap.extra.oldoverflow.
        // overflow and oldoverflow are only used if key and elem do not contain pointers.
        // overflow contains overflow buckets for hmap.buckets.
        // oldoverflow contains overflow buckets for hmap.oldbuckets.
        // The indirection allows to store a pointer to the slice in hiter.
        overflow    *[]*bmap
        oldoverflow *[]*bmap

        // nextOverflow holds a pointer to a free overflow bucket.
        nextOverflow *bmap
    }

    注意:扩容是迫不得已才进行扩容的,能不扩容则不扩容。当超过负载因子的时候,先用溢出桶方案进行间接扩容

go语言map扩容规则
    1,map的count在预先申请的内存中存满了,则优先使用溢出桶,作为简介扩容方案。

    2扩容条件:
        当使用的溢出桶过多,则需要进行扩容。当超过负载因子(go为6.5)的时候进行翻倍扩容
        负载因子未超标,却有很多溢出桶的情况,进行等量扩容(map删除很多元素的情况下)

函数

一个进程必须有:代码段,堆栈段,数据段
简单调用过程
    函数调用过程中,call指令,跳转到被调用函数入口。被调用函数执行完毕,ret指令跳回调用处继续执行

栈帧,分配给函数的栈空间
栈基,函数栈帧的栈底
栈指针,栈顶

go语言函数栈帧布局:

    |调用者栈基地址|
    |局部变量|
    |返回值(调用函数的返回值)|
    |参数|

    解析:1,被调用函数是通过栈指针+偏移量定位到返回值和参数
        2,go语言的栈帧不是逐步变大,而是直接分配好栈帧,栈指针指向开头,然后通过栈指针+偏移量定位指令


call指令:
    1,下一条指令的地址入栈
    2,跳转到被调用函数入口处执行

ret执行:
    1,弹出调用函数下一条的指令地址
    2,跳到调用函数的下一条指令地址继续执行调用函数

执行过程:
    调用函数,执行call指令,先入栈下一条指令的地址
    call函数跳到被调用函数入口
    被调用函数开始执行,开辟栈帧(修改bp,sp寄存器的值即可)
    被调用函数执行完毕,恢复调用者栈基
    执行ret,弹出返回地址
    跳到调用函数下一条指令地址,进行执行



注意的问题:
    1,go函数中,return语句执行结束,再执行defer函数
    2,go函数中,如若调用者指定了返回值,被调用函数不需要再定义,此值并非被调用函数的局部变量
        修改此值都会在调用函数生效。

闭包

1闭包函数,有状态的函数
在函数执行过程中,会分配funcValue结构体。指向函数地址。
状态参数固定值,则拷贝即可。状态函数非固定值(有修改情况),则堆上分配状态参数的地址。如果闭包执行多次,
最后状态函数都会给修改。

最终目标:
    闭包函数底层设计的最终目标,其实就是保持状态参数,参数,返回值的一致性。