Go 的内存对齐
基础概念类面试题
1. 什么是内存对齐?为什么需要内存对齐?
考察点: 基础概念理解
参考答案: 内存对齐是指数据在内存中按照一定规则排列,使变量的首地址是特定值的倍数。现代计算机虽然可以从任意地址访问数据,但合理的内存对齐可以:
- 提高内存访问效率:处理器可以在一次操作中读取整个变量
- 支持原子操作:对齐的变量访问是原子的,对并发编程重要
- 优化缓存利用:减少缓存行的浪费和竞争
注意: 内存对齐指的是首地址对齐,不是变量大小对齐。
2. Go 语言的内存对齐规则是什么?
考察点: Go 语言特定知识
参考答案:
-
基本类型对齐:对齐值通常等于其字节大小
bool,int8: 1字节对齐int16: 2字节对齐int32,float32: 4字节对齐int64,float64: 8字节对齐
-
结构体对齐:对齐值是所有字段中最大对齐值
-
内存分配对齐:通常按8字节对齐
性能优化类面试题
3. 请画图说明内存对齐如何提高访问效率
考察点: 深度理解和表达能力
4. 如何优化结构体的内存布局?请给出具体例子
考察点: 实际应用能力
参考答案: 优化原则:将字段按对齐要求从大到小排序
// 未优化的结构体
type BadStruct struct {
A bool // 1字节
B int64 // 8字节
C bool // 1字节
D int32 // 4字节
}
// 大小:24字节
// 优化后的结构体
type GoodStruct struct {
B int64 // 8字节
D int32 // 4字节
A bool // 1字节
C bool // 1字节
}
// 大小:16字节
代码分析类面试题
5. 分析下面代码的输出,并解释原因
package main
import (
"fmt"
"unsafe"
)
type Example struct {
A bool
B int32
C float64
}
func main() {
example := Example{}
fmt.Printf("Size: %d\n", unsafe.Sizeof(example))
fmt.Printf("Offset A: %d\n", unsafe.Offsetof(example.A))
fmt.Printf("Offset B: %d\n", unsafe.Offsetof(example.B))
fmt.Printf("Offset C: %d\n", unsafe.Offsetof(example.C))
}
考察点: unsafe包使用和内存布局理解
参考答案:
Size: 16
Offset A: 0
Offset B: 4
Offset C: 8
内存布局图:
解释:
- A占1字节,但B需要4字节对齐,所以A后填充3字节
- B占4字节,C需要8字节对齐,B后无需填充
- 总大小16字节,符合最大字段(8字节)的对齐要求