You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go中空结构体为何不占内存?作为结构体字段时内存占用为何有差异?

关于Go中空结构体的内存占用与对齐问题

1. 空结构体struct{}为何不占用内存?变量如何存储?

  • Go语言规范明确空结构体的大小为0,因为它没有任何字段,不需要存储任何数据。
  • 对于a := struct{}{}这类变量,编译器会做特殊优化:栈上不会为它分配实际的存储空间。编译阶段就会把它的引用直接处理掉,运行时不存在对应的栈内存。它更像是一个语法层面的“占位符”,仅用于满足类型要求,无需实际存储。

2. 空结构体作为结构体字段时是否占用内存?

空结构体本身大小为0,但作为结构体字段时,是否会增加整个结构体的大小,完全取决于内存对齐规则和字段排列顺序。结合你给出的实验结果分析:

实验代码

type EmptyStruct struct {}

type st1 struct {
    a int64
}

type st2 struct {
    a int64
    b struct{}
}

type st3 struct {
    b struct{}
    a int64
}

func main() {
    const format string = "%-3s: size: %-2d, val: %v\n"

    es := EmptyStruct{}
    s1 := st1{}
    s2 := st2{}
    s3 := st3{}

    fmt.Printf(format, "es", unsafe.Sizeof(es), es)
    fmt.Printf(format, "s1", unsafe.Sizeof(s1), s1)

    fmt.Printf(format, "s2", unsafe.Sizeof(s2), s2)
    fmt.Printf("\t"+format, "s2.a", unsafe.Sizeof(s2.a), s2.a)
    fmt.Printf("\t"+format, "s2.b", unsafe.Sizeof(s2.b), s2.b)

    fmt.Printf(format, "s3", unsafe.Sizeof(s3), s3)
    fmt.Printf("\t"+format, "s3.a", unsafe.Sizeof(s3.a), s3.a)
    fmt.Printf("\t"+format, "s3.b", unsafe.Sizeof(s3.b), s3.b)
}

实验输出

es : size: 0 , val: {}
s1 : size: 8 , val: {0}
s2 : size: 16, val: {0 {}}
        s2.a: size: 8 , val: 0
        s2.b: size: 0 , val: {}
s3 : size: 8 , val: {{} 0}
        s3.a: size: 8 , val: 0
        s3.b: size: 0 , val: {}

结果分析

  • st1仅包含int64类型字段,大小为8字节,和int64本身的大小一致。
  • st2字段顺序为int64 a + struct{} b:
    Go的内存对齐规则要求,结构体的总大小必须是其最大字段对齐边界的整数倍。int64的对齐边界是8字节,当a占满8字节后,空结构体b虽然本身不占空间,但为了让整个结构体满足对齐要求,编译器会自动填充8字节,最终总大小为16字节(8的2倍)。
  • st3字段顺序为struct{} b + int64 a:
    空结构体b被放在开头,编译器会直接把它“合并”到后续int64 a的对齐空间中——因为空结构体不需要实际存储,所以整个结构体的大小就是int64的8字节,无需额外填充。

验证内存对齐的方法

可以通过unsafe.Offsetof查看字段的内存偏移量,在main函数中添加以下代码:

fmt.Printf("s2.a offset: %d, s2.b offset: %d\n", unsafe.Offsetof(s2.a), unsafe.Offsetof(s2.b))
fmt.Printf("s3.b offset: %d, s3.a offset: %d\n", unsafe.Offsetof(s3.b), unsafe.Offsetof(s3.a))

运行后会得到如下输出:

s2.a offset: 0, s2.b offset: 8
s3.b offset: 0, s3.a offset: 0

这个结果直接验证了:

  • s2中b的偏移量是8,紧跟在a之后,而结构体需要对齐到8字节倍数,所以总大小为16字节(含8字节填充)。
  • s3中a和b的偏移量都是0,二者共享同一内存位置(因为空结构体无需存储),所以总大小为8字节。

内容的提问来源于stack exchange,提问作者AquaOwO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 08:37:45