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 程序的性能!

相关推荐
程序猿追23 分钟前
我搭了个网页工具:输入关键词,SERP API 自动吐出比价 Excel
后端
Lee川25 分钟前
RAG 实战:从一篇掘金文章出发,拆解检索增强生成的全链路
前端·人工智能·后端
Lee川38 分钟前
MCP 高德地图实战:当 AI 学会使用工具,一个协议如何重塑大模型的行动边界
前端·人工智能·后端
楼田莉子1 小时前
C++17新特性:__had_include/属性/求值顺序规则
开发语言·c++·后端
程序员cxuan1 小时前
Codex 把我家烂网给优化后,我 TM 直接原地起飞了。
人工智能·后端·程序员
IT_陈寒1 小时前
Redis批量删除踩了坑,原来DEL命令不是万能的
前端·人工智能·后端
叫我少年2 小时前
C# 命名空间与 using 指令 — 文件范围、全局导入、别名
后端
我是一颗柠檬3 小时前
【MySQL全面教学】MySQL基础SQL语句Day3(2026年)
数据库·后端·sql·mysql·oracle
No8g攻城狮3 小时前
【AI工具】wsl2 + ubuntu22.04安装部署sub2api详细教程
人工智能·ai·go·vue
老毛肚4 小时前
Spring boot 特性和自写Reids组件
java·spring boot·后端