✅ 一句话总结:
Go 的结构体不是简单相加大小,而是根据对齐规则填充 padding(填充字节),最终大小必须是最大对齐值的倍数。
为什么要关心对齐
- 你正在编写的代码在性能(CPU、Memory)方面有一定的要求
- 你正在处理向量方面的指令
- 某些硬件平台(ARM)体系不支持未对齐的内存访问
为什么要做对齐
- 平台(移植性)原因:不是所有的硬件平台都能够访问任意地址上的任意数据。例如:特定的硬件平台只允许在特定地址获取特定类型的数据,否则会导致异常情况
- 性能原因:若访问未对齐的内存,将会导致 CPU 进行两次内存访问,并且要花费额外的时钟周期来处理对齐及运算。而本身就对齐的内存仅需要一次访问就可以完成读取动作

在上图中,假设从 Index 1 开始读取,将会出现很崩溃的问题。因为它的内存访问边界是不对齐的。因此 CPU 会做一些额外的处理工作。如下:
- CPU 首次读取未对齐地址的第一个内存块,读取 0-3 字节。并移除不需要的字节 0
- CPU 再次读取未对齐地址的第二个内存块,读取 4-7 字节。并移除不需要的字节 5、6、7 字节
- 合并 1-4 字节的数据
- 合并后放入寄存器
从上述流程可得出,不做 “内存对齐” 是一件有点 "麻烦" 的事。因为它会增加许多耗费时间的动作
而假设做了内存对齐,从 Index 0 开始读取 4 个字节,只需要读取一次,也不需要额外的运算。这显然高效很多,是标准的空间换时间做法
一、先看结构体定义
type Test struct {
a bool // 1
b int32 // 4
c int8 // 1
d int64 // 8
e byte // 1
}
单独大小确实是:
1 + 4 + 1 + 8 + 1 = 15 字节
但 Go 不允许你这样省空间,因为「对齐」。
二、对齐规则最容易误解,看我简化后的版本
对齐规则(简化版)
① 每个字段必须放在 它对齐值的整数倍偏移地址上
|
类型 |
大小 |
对齐值 |
|
bool |
1 |
1 |
|
int8 |
1 |
1 |
|
byte |
1 |
1 |
|
int32 |
4 |
4 |
|
int64 |
8 |
8 |
② 结构体整体大小必须是 最大对齐值(这里是 8) 的整数倍
三、按顺序计算内存布局(会发现 padding 出现了)
⭐ 步骤 1:字段 a(bool)
|
字段 |
对齐值 |
当前偏移 |
可放? |
放到偏移 |
占用 |
|
a |
1 |
0 |
0 % 1 = 0 ✔ |
0 |
1B |
⭐ 步骤 2:字段 b(int32)
b 对齐值是 4
当前 offset=1
但 1 不是 4 的倍数,必须填 padding,填到 4 位置。
所以需要补:4 - (1 % 4) = 3 字节
|
填充 |
新偏移 |
|
+3 |
offset = 4 |
然后放 b,占 4 字节:
offset = 4 + 4 = 8
⭐ 步骤 3:字段 c(int8)
int8 对齐值 = 1 → 没问题
c 放在 offset 8,占 1 字节
offset = 9
⭐ 步骤 4:字段 d(int64)
对齐值 8
当前 offset=9
但 9 % 8 = 1 ≠ 0
需要补齐到下一个 8 对齐地址:16
16 - 9 = 7 字节 padding
offset = 16
放 d,占 8 字节:
offset = 16 + 8 = 24
⭐ 步骤 5:字段 e(byte)
byte 对齐值=1,无需对齐
放在 offset=24,占 1 字节
offset = 25
⭐ 步骤 6:结构体整体对齐
结构体的对齐值 = 最大字段对齐值 = 8
但当前结构体大小=25
必须让 25 补齐到 8 的倍数:
下一个 8 的倍数是 32
所以需要额外 padding:
32 - 25 = 7 字节
最终结构体大小 = 32 字节
🎉 四、你看到的最终 layout(图示)
a xxx | bbbb | c xxx | xxx | dddd dddd | e xxx | xxx
0 4 8 16 24 25 32(end)
更清晰一点(每段代表 4 字节):
[ a . . . ] [ b b b b ] [ c . . . ] [ . . . . ]
[ d d d d ] [ d d d d ] [ e . . . ] [ . . . . ]
. 表示 padding(填充字节)
五、实验输出结果
Test size: 32, align: 8
六、为什么 Go 有这种对齐机制?
为了 CPU 高效访问内存。
CPU 访问 misaligned memory(未对齐地址)速度会变慢,甚至在某些平台会直接报错。
所以 Go 编译器自动对齐字段,让结构体在内存中更高效。
如果想让结构体更节省空间怎么办?
👉 调整字段顺序(从大到小)
type Test2 struct {
d int64
b int32
a bool
c int8
e byte
}
854

被折叠的 条评论
为什么被折叠?



