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

相关推荐
永远不会的CC5 小时前
浙江华昱欣实习(4月23日~ 4月19日)
后端·学习
直奔標竿5 小时前
Java开发者AI转型第二十五课!Spring AI 个人知识库实战(四)——RAG来源追溯落地,拒绝AI幻觉
java·开发语言·人工智能·spring boot·后端·spring
嘟嘟MD5 小时前
程序员副业 | 2026年4月复盘
后端·创业
时空系5 小时前
认识Rust——我的第一个程序 Rust中文编程
开发语言·后端·rust
DevilSeagull6 小时前
Windows 批处理 (Batch) 编程: 从入门到入土. (一) 基础概念与环境配置
开发语言·windows·后端·batch·语言
CAE虚拟与现实6 小时前
五一假期闲来无事,来个前段、后端的说明吧
前端·后端·vtk·three.js·前后端
0xDevNull6 小时前
Java泛型详解
java·开发语言·后端
yeeanna6 小时前
GO函数的特殊性
开发语言·后端·golang
时空系6 小时前
第6篇:数据容器——管理大量数据 Rust中文编程
开发语言·后端·rust
eLIN TECE6 小时前
Go基础之环境搭建
开发语言·后端·golang