Go结构体优化(对齐方式)

Go 语言和 C 语言类似,结构体的成员必须按照它们的对齐要求存储。编译器会自动填充对齐字节,确保每个字段的起始地址符合 CPU 的对齐规则。

示例

go 复制代码
package main

import (
    "fmt"
    "unsafe"
)

type A struct {
    a int8
    b uint32
    c int16
}

func main() {
    fmt.Printf("Offsetof(A.a) = %d\n", unsafe.Offsetof(A{}.a))
    fmt.Printf("Offsetof(A.b) = %d\n", unsafe.Offsetof(A{}.b))
    fmt.Printf("Offsetof(A.c) = %d\n", unsafe.Offsetof(A{}.c))
    fmt.Printf("Sizeof(A) = %d\n", unsafe.Sizeof(A{}))
}

/*
Output:
Offsetof(A.a) = 0
Offsetof(A.b) = 4
Offsetof(A.c) = 8
Sizeof(A) = 12
*/

内存布局

因为 b 需要4字节对齐,所以编译器会在 a 之后填充3个字节。又因为结构体的大小必须是其最大对齐方式(4字节)的整数倍,所以最终结构体 A 的大小为12个字节。

优化

go 复制代码
package main

import (
    "fmt"
    "unsafe"
)

type AOptimized struct {
    a int8
    c int16
    b uint32
}

func main() {
    fmt.Printf("Offsetof(AOptimized.a) = %d\n", unsafe.Offsetof(AOptimized{}.a))
    fmt.Printf("Offsetof(AOptimized.b) = %d\n", unsafe.Offsetof(AOptimized{}.b))
    fmt.Printf("Offsetof(AOptimized.c) = %d\n", unsafe.Offsetof(AOptimized{}.c))
    fmt.Printf("Sizeof(AOptimized) = %d\n", unsafe.Sizeof(AOptimized{}))
}

优化后内存布局

因为 c 需要2字节对齐,所以编译器会在 a 之后填充1个字节。此时结构体的实际大小为8个字节,刚好是最大对齐方式(4字节)的整数倍,所以最终结构体 A 的大小为8个字节。

结论

Go 结构体需要关注对齐

  • 和 C 语言一样,Go 结构体会自动填充来对齐字段。
  • 不合理的字段排列会浪费内存。
  • 使用 unsafe.Sizeof()unsafe.Offsetof() 了解结构体的内存布局。

结构体优化可以减少内存占用

  • 合理排序字段,减少填充。

合理优化结构体,可以减少内存占用,提高 Go 程序的性能!

相关推荐
笃行3505 小时前
SQLServer数据迁移之后,那张报表还能不能秒出
后端
LucianaiB5 小时前
别再被 AI 骗了:我把腾讯云 4 个 Skill 做成了个「AI 打假侦探」,过程的一个小配置坑惨了我
后端
candyTong6 小时前
Claude Code 如何恢复一段会话
后端·架构·ai编程
En^_^Joy7 小时前
Django项目配置全攻略:settings配置文件
后端·python·django
IT_陈寒10 小时前
Python线程池吞了异常还不告诉我,这谁顶得住啊
前端·人工智能·后端
小强库计算机毕业设计10 小时前
SpringBoot+Vue3 学生宿舍管理系统实战
java·spring boot·后端·vue·学生宿舍管理系统
小狼18310 小时前
实践6|SDD 实战:AI 写的规格被推翻了四次
后端·claude
篮框坏了10 小时前
"DeepSeek Harness 实测:一毛钱干三活,但默认配置是个坑"
后端·ai编程
jobBridge2110 小时前
大模型到底是怎么"想"的?我把 Transformer 拆开,发现它其实是个"接词狂魔"
人工智能·后端·编程语言
唐青枫11 小时前
看懂内存地址之后,才算真正入门 Zig:指针、切片与实战
后端