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

为何新增打印语句后Go语言结构体指针比较结果变为true?

问题:空结构体指针比较结果随代码变更异常变化

我编写了如下Go语言代码:

package main

import "fmt"

type MyStruct struct {
}

func main() {
    a := &MyStruct{}
    b := &MyStruct{}

    fmt.Println(a == b)
    fmt.Println(*a == *b)
}

输出符合预期:

false
true

但当我在末尾新增两句打印语句后:

package main

import "fmt"

type MyStruct struct {

}

func main() {
   a := &MyStruct{}
   b := &MyStruct{}

   fmt.Println(a == b)
   fmt.Println(*a == *b)
   fmt.Println(&a)
   fmt.Println(&b)
}

输出变为:

true
true
0xc0000ae018
0xc0000ae020

为何此时第一行的指针比较结果变为true?


解答

核心原因:Go编译器对空结构体的内存优化

  • 空结构体的特性:struct{}(空结构体)的大小为0,它的实例不占用任何内存空间。所有空结构体实例在逻辑上完全等价,没有任何区别。
  • 编译器的指针复用优化:Go编译器会针对空结构体做特殊优化——当代码中创建多个指向空结构体的指针时,编译器会尽可能让这些指针指向同一个内存地址。因为空结构体没有字段,复用地址不会影响程序逻辑,还能减少内存开销。不过这种优化的触发会依赖代码上下文,并非固定触发。

两个示例的差异分析

  1. 第一个示例(无新增打印)
    仅创建两个空结构体指针并直接比较,此时编译器可能未触发指针复用优化,a和b指向了不同的(无实际意义的)内存地址,因此a == b返回false。

  2. 第二个示例(新增打印&a、&b)
    新增的fmt.Println(&a)和fmt.Println(&b)打印的是指针变量a和b自身的内存地址(而非它们指向的空结构体地址)。此时编译器的优化策略调整,判定可以安全复用空结构体的指针地址,于是让a和b指向了同一个地址,导致a == b返回true。

验证方式

如果在第二个示例中添加一行打印a和b本身值的代码:

fmt.Println(a, b)

会输出两个完全相同的地址,直接印证了指针被复用的结论。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 14:20:59