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

Golang中空struct指针比较结果异常原因咨询

Go中零大小struct实例比较结果随Printf调用变化的原因

先看你提供的代码:

package main

import "fmt"

func main() {
    type s struct{}
    s1 := new(s)
    s2 := new(s)
    // fmt.Printf("%p\n", s1)
    // fmt.Printf("%p\n", s2)
    fmt.Println(s1 == s2)
}

这个现象的核心原因在于Go的变量逃逸分析和零大小类型的内存分配优化:

  1. 注释Printf时的情况
    s1和s2是局部变量,编译器会将它们分配在栈上。尽管struct{}是零大小类型,但栈帧中会为每个变量保留一个逻辑占位位置,这导致s1和s2的栈地址并不相同,因此指针比较结果为false。

  2. 取消注释Printf时的情况
    fmt.Printf("%p", ...)需要接收指针参数,而且由于fmt.Printf是可变参数函数,编译器无法确定它不会长期持有这些指针,于是会将s1和s2标记为必须逃逸到堆上。而Go运行时对堆上的零大小类型实例有特殊优化:所有零大小实例会复用同一个内存地址(因为它们不需要实际存储空间),此时s1和s2指向同一个地址,指针比较结果自然为true。

需要注意的是,Go语言规范并没有强制要求零大小类型的所有实例地址必须相同,只是运行时在堆分配场景下会做复用优化;栈上的零大小变量地址则由栈帧布局决定,可能存在差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 02:58:15