本文最后更新于 2024-05-16,文章内容可能已经过时。

1.切片:

type slice struct {
    array unsafe.Pointer 
    len   int
    cap   int
}

在切片达到容量上限时,继续 append 操作会导致切片扩容。扩容是为切片分配新的内存空间并拷贝原切片中元素的过程。

如果go 1.18+,原来的slice 容量oldcap小于256的时候,新 slice 的容量newcap是oldcap 的2倍;当oldcap容量大于等于 256 的时候,newcap会有个计算公式:newcap += (newcap +3*threshold) / 4 再对 newcap 作了一个内存对齐,这个和内存分配策略相关。进行内存对齐之后,新 slice 的容量是要大于等于按照前半部分生成的newcap。

线程不安全:手动channel.锁

2.哈希表:

数据结构:

hmap,[]bmap,溢出桶.

两次哈希:前八位

线程不安全

3.defer:

最后声明的 defer 语句会被最先执行。 关于修改返回值, defer 语句在函数返回之后执行,但是它可以访问并修改返回值。 这是因为返回值在函数结束时会被当作 defer 语句的参数。

4.gc:

三色,对应了垃圾回收过程中对象的三种状态:

  • 灰色:对象还在标记队列中等待

  • 黑色:对象已被标记,gcmarkBits 对应位为 1 (该对象不会在本次 GC 中被回收)

  • 白色:对象未被标记,gcmarkBits 对应位为 0 (该对象将会在本次 GC 中被清理)

根对象在垃圾回收的术语中又叫做根集合,它是垃圾回收器在标记过程时最先检查的对象,包括:

  • 全局变量:程序在编译期就能确定的那些存在于程序整个生命周期的变量。

  • 执行栈:每个 goroutine 都包含自己的执行栈,这些执行栈上指向堆内存的指针。 寄

  • 存器:寄存器的值可能表示一个指针,参与计算的这些指针可能指向某些赋值器分配的堆内存区块。

Go V1.8版本引入了混合写屏障机制(hybrid write barrier),避免了对栈re-scan的过程,极大的减少了STW的时间。结合了两者的优点。

  • GC开始将栈上的对象全部扫描并标记为黑色。

  • GC期间,任何在栈上创建的新对象,均为黑色。

  • 被删除的对象标记为灰色。

  • 被添加的对象标记为灰色。

5.gm

全局的协程队列+线程池维护内核态线程

6.gmp:

更加灵活地进行协程之间的调度。

P(Processor):虚拟处理器,M执行G所需要的资源和上下文,只有将 P 和 M 绑定,才能让 P 的 runq 中的 G 真正运行起来。P 的数量决定了系统内最大可并行的 G 的数量

全局队列+每个p本地队列的方式,简化锁的开销。

work stealing:

干完活的线程与其等着,不如去帮其他线程干活。

hand off:

当前线程M阻塞时,释放P,给其它空闲的M处理.