一、基本数值类型
1.1 整型
整型在内存中存储方式取决于系统架构:
1.2 浮点型
遵循 IEEE 754 标准:
1 2 3 4 5 6 7 8 9 10 11
| float32 (32位): ┌────────┬────────────────────────────┐ │ 符号位 │ 指数位(8位) │ 尾数位(23位) │ │ 1bit │ 8bits │ 23bits │ └────────┴────────────────────────────┘
float64 (64位): ┌────────┬─────────────────────────────┬─────────────────────────────┐ │ 符号位 │ 指数位(11位) │ 尾数位(52位) │ │ 1bit │ 11bits │ 52bits │ └────────┴─────────────────────────────┴─────────────────────────────┘
|
二、字符串 string
2.1 底层结构
1 2 3 4 5
| type stringStruct struct { str unsafe.Pointer len int }
|
1 2 3 4 5 6 7 8 9 10 11 12
| 字符串 "hello" 的内存布局:
stringStruct ┌─────────────┬─────────────┐ │ str (指针) │ len = 5 │ └──────┬──────┴─────────────┘ │ ▼ ┌─────┬─────┬─────┬─────┬─────┐ │ 'h' │ 'e' │ 'l' │ 'l' │ 'o' │ └─────┴─────┴─────┴─────┴─────┘ [0] [1] [2] [3] [4]
|
2.2 关键特性
不可变性:字符串内容存储在只读段,修改会触发新分配。
零拷贝切片:
1 2
| s := "hello world" sub := s[0:5]
|
三、切片 slice
3.1 底层结构
1 2 3 4 5 6
| type slice struct { ptr unsafe.Pointer len int cap int }
|
1 2 3 4 5 6 7 8 9 10 11
| 切片 s := make([]int, 3, 5):
slice ┌──────────┬──────────┬──────────┐ │ ptr │ len = 3 │ cap = 5 │ └────┬─────┴──────────┴──────────┘ │ ▼ ┌───┬───┬───┬───┬───┐ │ 0 │ 0 │ 0 │ │ │ └───┴───┴───┴───┴───┘
|
3.2 扩容规则
1 2 3 4 5 6 7 8 9
| if len < 1024 { newcap = doublecap } else { for newcap < newLen { newcap += newcap / 4 } }
|
3.3 切片共享底层数组
1 2 3 4
| a := []int{1, 2, 3, 4, 5} b := a[1:3]
b[0] = 99
|
四、映射 map
4.1 底层结构
1 2 3 4 5 6 7 8 9 10 11 12
| type hmap struct { count int flags uint8 B uint8 noverflow uint16 hash0 uint32 buckets unsafe.Pointer oldbuckets unsafe.Pointer nevacuate uintptr extra *mapextra }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| map 内部结构:
hmap ┌─────────┬───────┬─────┬──────────┬──────────┐ │ count │ flags │ B │ hash0 │ buckets │ └─────────┴───────┴─────┴──────────┴────┬─────┘ │ ▼ ┌─────────────────────┐ │ buckets (2^B 个桶) │ │ ┌────┬────┬────┬────┐│ │ │bmap│bmap│bmap│bmap││ │ └────┴────┴────┴────┘│ └─────────────────────┘
每个桶 bmap: ┌─────────────────────────────┐ │ tophash [8]uint8 │ ← 高8位哈希,快速比对 │ keys [8]keyType │ ← 8个key │ values [8]valueType │ ← 8个value │ overflow *bmap │ ← 溢出桶指针 └─────────────────────────────┘
|
4.2 查找流程
1 2 3 4 5 6 7
| 查找 map[key]:
1. 计算 hash := hashFunc(key) + hash0 2. 取低B位确定桶: bucket = hash & (2^B - 1) 3. 取高8位快速比对: tophash = hash >> 56 4. 遍历桶内元素,找到则返回 5. 未找到则检查溢出桶
|
4.3 扩容机制
触发条件:
- 负载因子 > 6.5 (元素太多)
- 溢出桶过多 (元素分布不均)
扩容是渐进式的,每次操作迁移少量数据。
五、通道 channel
5.1 底层结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| type hchan struct { qcount uint dataqsiz uint buf unsafe.Pointer elemsize uint16 closed uint32 elemtype *_type sendx uint recvx uint recvq waitq sendq waitq lock mutex }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| channel 结构:
hchan ┌─────────────┬─────────────┬─────────────┐ │ qcount │ dataqsiz │ elemsize │ ├─────────────┼─────────────┼─────────────┤ │ closed │ sendx │ recvx │ ├─────────────┼─────────────┼─────────────┤ │ recvq │ sendq │ lock │ └──────┬──────┴──────┬──────┴─────────────┘ │ │ ▼ ▼ recvq 环形队列 buf (等待队列) ┌───┬───┬───┬───┐ │ 1 │ 2 │ │ │ └───┴───┴───┴───┘
|
5.2 发送接收流程
1 2 3 4 5 6 7 8
| 发送 ch <- x:
1. 加锁 2. 检查 recvq 是否有等待者 → 有:直接把数据拷贝给等待者,唤醒它 3. 检查 buf 是否有空位 → 有:写入 buf[sendx] 4. 加入 sendq 等待
|
六、接口 interface
6.1 空接口 eface
1 2 3 4
| type eface struct { _type *_type data unsafe.Pointer }
|
6.2 非空接口 iface
1 2 3 4 5 6 7 8 9 10 11
| type iface struct { tab *itab data unsafe.Pointer }
type itab struct { inter *interfacetype _type *_type hash uint32 fun [1]uintptr }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 非空接口 var r io.Reader = &os.File{}:
iface ┌─────────────┬─────────────┐ │ tab (itab) │ data │ └──────┬──────┴──────┬──────┘ │ │ ▼ ▼ itab os.File实例 ┌─────────────┐ │ inter │ (io.Reader) │ _type │ (*os.File) │ fun[0] │ → Read() └─────────────┘
|
七、结构体 struct
7.1 内存对齐
1 2 3 4 5 6
| type Person struct { Name string Age int Sex bool }
|
7.2 字段重排优化
1 2 3 4 5 6 7 8 9 10 11 12 13
| type Bad struct { a bool b int64 c bool }
type Good struct { b int64 a bool c bool }
|
八、总结
| 类型 |
底层核心 |
关键特性 |
| string |
ptr + len |
不可变、零拷贝切片 |
| slice |
ptr + len + cap |
动态扩容、共享底层数组 |
| map |
hmap + bmap |
哈希桶、渐进扩容 |
| channel |
hchan + ring buffer |
锁 + 等待队列 |
| interface |
eface/iface + itab |
类型信息 + 方法表 |
理解底层实现有助于写出更高效、更安全的 Go 代码。