Daily Study
更新: 11/26/2025 字数: 0 字 时长: 0 分钟
Daily Plan
#todo
- [ ]
Go的细节知识回顾
new和make的区别
核心总结
| 特性 | new(T) | make(T, args) |
|---|---|---|
| 用途 | 分配内存并清零。 | 初始化引用类型的数据结构。 |
| 返回 | 指针(*T)。 | 引用类型值(T)。 |
| 适用类型 | 所有类型。 | 仅限于 slice, map, channel。 |
map的扩容策略
map底层是hash表,核心结构是hamp(头)和bucket(基本存储单元),采用链表法来解决哈希冲突。
Go Map 的扩容过程确实包括这两种不同机制,以应对不同的性能问题。
| 扩容类型 | 触发条件 | 桶数量 (2B) | 目标 |
|---|---|---|---|
| 双倍扩容 | 负载因子过高 (>6.5) | N→2N | 扩大容量,提高性能 |
| 等量扩容 | 溢出桶过多 / 大量删除后 | N→N | 整理结构,消除溢出桶 |
扩容过程(核心机制)
一旦触发扩容,会发生以下步骤:
双倍扩容: 创建一个新的主桶数组,大小是旧桶数组的两倍(即
B增加 1)。旧桶数组被赋值给hmap.oldbuckets。渐进搬迁 (Evacuation): 新旧桶数据不会一次性全部复制。每次对 Map 进行读写操作时(包括查找、插入、删除):
Go 运行时会顺带搬迁两个旧桶及其连接的所有溢出桶的数据到新桶数组中。
旧桶中的数据根据新的
B+1位哈希值重新分配到新桶中的两个位置(i 和 i+Nold)。
完成: 当
hmap.oldbuckets中的所有桶都搬迁完毕后,旧的桶数组被释放,扩容完成。
这种渐进式搬迁机制将高延迟的扩容操作分散到了多次的 Map 操作中,从而保证了 Map 在高并发场景下的持续高性能。
