如何在Golang中理解指针比较_Golang地址比较与相等判断
技术百科
P粉602998670
发布时间:2026-01-01
浏览: 次 Go中指针相等仅取决于是否指向同一内存地址或同为nil;==比较不关心值、内容或结构体字段,不同类型指针不可比较,零大小结构体指针可能因地址复用而意外相等。
Go 中两个指针相等,只看它们是否指向**同一块内存地址**,或是否都为 nil;值相同、结构体内容一样、甚至都是 &struct{}{},都不保证指针相等。
用 == 比较指针:只认地址,不认内容
Go 允许直接用 == 或 != 比较同类型指针,但结果完全取决于底层地址是否一致:
-
p1 == p2为true当且仅当p1和p2存储的是同一个地址(比如都指向变量a),或两者都是nil - 即使
*p1 == *p2成立(值相等),p1 == p2仍可能为false—— 它们只是“长得像”,不是“同一个人” - 不同类型指针(如
*int和*int64)无法直接比较,编译报错:mismatched types *int and *int64
func main() {
a, b := 42, 42
p1 := &a
p2 := &b
fmt.Println(p1 == p2) // false —— 不同变量,不同地址
fmt.Println(*p1 == *p2) // true —— 值相同,但和指针比较无关
}
结构体指针比较:地址相等 ≠ 内容相等
对结构体指针使用 ==,比的是指针本身,不是它指向的字段。想比内容,必须解引用:
-
p1 == p2:只在p1和p2是同一个结构体实例的地址时才为true -
*p1 == *p2:要求结构体所有字段可比较(不能含[]int、map[string]int或函数),否则编译失败 - 若结构体含指针字段(如
data *string),*p1 == *p2仍只比指针地址,不比*data的值
type User struct {
Name string
Age int
}
u1 := &User{"Alice", 30}
u2 := &User{"Alice", 30}
fmt.Println(u1 == u2) // false
fmt.Println(*u1 == *u2) // true —— 字段都可比较,且值相同
零大小结构体指针的“幻影相等”
这是最容易踩坑的冷知识:指向 struct{} 这类零大小变量的指针,在接口中比较时可能“意外相等”,哪怕它们来自不同调用:
- Go 规范明确允许:指向不同零大小变量的指针“可能相等,也可能不相等”
- 实际中,编译器常复用同一地址(因为不占空间),导致
&struct{}{}多次调用返回的指针地址相同 - 一旦包装进
interface{},one == two可能返回true,但你根本没创建同一个对象 - 解决办法很简单:让结构体非零大小(加一个
byte字段或注释字段即可)
type fake struct{ _ [0]byte } // 非零大小,强制分配独立地址
// 而不是 type fake struct{} —— 危险!
函数指针不能直接比较,得靠 reflect
函数名本身不可比较:someFunc == someFunc 编译失败,报错 func can only be compared to nil:
- 唯一合法的函数比较是
f == nil - 要判断两个函数是否是同一个实体,必须用
reflect.ValueOf(f).Pointer() - 注意:该地址是运行时函数入口地址,跨构建/热重载可能变化,不适用于持久化或网络传输
import "reflect"
func foo() {}
func bar() {}
fmt.Println(reflect.ValueOf(foo).Pointer() == reflect.ValueOf(foo).Pointer()) // true
fmt.Println(refl
ect.ValueOf(foo).Pointer() == reflect.ValueOf(bar).Pointer()) // false
真正难的不是写对 ==,而是意识到你在比什么——地址?值?语义唯一性?一旦把 == 当成“逻辑相等”用,尤其混入接口、零大小类型或函数,就很容易被 Go 的底层行为反向教育。
# ai
# 的是
# 都是
# 这是
# 你在
# 都不
# 也可
# 复用
# 不同类型
# go
# golang
# 对象
# String
# int
# 指针
# 接口
# nil
# 报错
# pointer
# red
# Interface
# 结构体
# Struct
# map
# 装进
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Windows11如何设置专注助手_Windows
- 如何在 Go 中正确反序列化多个同级 XML 元素
- 如何使用Golang开发基础文件下载功能_Gola
- MAC怎么设置程序窗口永远最前_MAC窗口置顶插件
- MAC如何隐藏文件夹及文件_MAC终端命令隐藏与第
- windows系统找不到无线网络怎么办_windo
- Python大文件处理策略_内存优化说明【指导】
- Win11更新后变慢怎么办_Win11系统更新后卡
- win11如何清理传递优化文件 Win11为C盘瘦
- Win11怎么设置夜间模式_Windows11显示
- Python字符串处理进阶_切片方法解析【指导】
- Windows怎样关闭开始菜单推荐广告_Windo
- 如何在Golang中修改数组元素_通过指针实现原地
- 微信里的php文件怎么变mp4_微信接收php转m
- MAC怎么一键隐藏桌面所有图标_MAC极简模式切换
- SAX解析器是什么,它与DOM在处理大型XML文件
- Python文件管理规范_工程实践说明【指导】
- 如何使用Golang模拟请求超时_Golang c
- Mac怎么设置鼠标滚动速度_Mac鼠标设置详细参数
- VSC怎样在VSC中调试PHPAPI_接口调试技巧
- Win10电脑怎么设置网络名称_Windows10
- 如何在 Go 项目开发中正确处理本地包导入与远程模
- Win11任务栏怎么放到顶部_Win11修改任务栏
- 如何使用Golang处理网络超时错误_Golang
- php打包exe如何加密代码_防反编译保护方法【技
- 跨文件调用类方法怎么用_php作用域操作符与自动加
- php8.4匿名类怎么用_php8.4匿名类创建与
- Win11怎么打开旧版计算器_Win11恢复传统计
- 如何在Golang中引入测试模块_Golang测试
- c++的位运算怎么用 与、或、异或、移位操作详解【
- Win11怎么设置任务栏图标大小_Windows1
- c++怎么编写动态链接库dll_c++ __dec
- MAC如何启用访达侧边栏显示_MAC Finder
- Linux怎么修改用户密码_Linux系统pass
- Win11怎样激活系统密钥_Win11系统密钥激活
- c++如何判断文件是否存在_c++ filesys
- 小程序里php怎么变mp4_小程序调用php生成m
- Win10怎样设置多显示器_Win10多显示器扩展
- Windows电脑键盘突然失灵怎么办?(驱动与硬件
- c++中如何使用auto关键字_c++11类型推导
- 如何高效获取循环末次生成的 NumPy 数组最后一
- Win11搜索栏无法输入_解决Win11开始菜单搜
- win11 OneDrive怎么彻底关闭 Win1
- Go语言中正确反序列化多个同级XML元素为结构体切
- Mac如何设置动态壁纸?(让桌面动起来)
- c++的mutex和lock_guard如何使用
- Win10如何卸载预装Edge扩展_Win10卸载
- c++ std::atomic如何保证原子性 c+
- 如何使用Golang配置安全开发环境_防止敏感信息
- PHP主流架构怎么部署到Docker_容器化流程【

ect.ValueOf(foo).Pointer() == reflect.ValueOf(bar).Pointer()) // false
QQ客服