多个goroutine同时读写指针指向的同一内存会导致数据竞争,需用sync.mutex或sync/atomic保护所指数据而非指针本身,并注意指针逃逸引发的悬垂问题。

多个 goroutine 同时读写同一指针指向的变量会出问题
Go 中指针本身不是并发不安全的根源,真正危险的是多个 goroutine 同时读写指针所指向的同一块内存。比如 int、struct 或 map 等类型被多个 goroutine 通过指针修改,就可能触发数据竞争(data race)。
运行时加 -race 参数能捕获这类问题,但很多情况它不会报错——比如只读+写混合、非原子更新字段、或指针指向未同步初始化的对象。
- 典型错误:多个 goroutine 调用
counter++,而counter是*int类型且未加锁 - 更隐蔽的问题:指针指向一个
sync.Map,但误以为“用了 sync.Map 就不用管指针了”——其实指针本身没保护,只是它指向的内容有内部同步 - 初始化竞态:一个全局
*Config指针在 init 阶段被赋值,但某个 goroutine 在 init 完成前就读取,得到 nil 或半初始化值
用 sync.Mutex 保护指针所指向的数据,而不是指针本身
指针变量(如 var p *int)的读写是原子的(在 64 位系统上),但它的值所指向的内存区域不是。所以锁的目标必须是“被指针访问的数据”,而非指针变量。
常见错误是把 mutex 放在指针外层、却忘了嵌套在结构体里;或者对每个指针单独加锁,导致锁粒度太粗或太细。
立即学习“go语言免费学习笔记(深入)”;
ECTouch是上海商创网络科技有限公司推出的一套基于 PHP 和 MySQL 数据库构建的开源且易于使用的移动商城网店系统!应用于各种服务器平台的高效、快速和易于管理的网店解决方案,采用稳定的MVC框架开发,完美对接ecshop系统与模板堂众多模板,为中小企业提供最佳的移动电商解决方案。ECTouch程序源代码完全无加密。安装时只需将已集成的文件夹放进指定位置,通过浏览器访问一键安装,无需对已有
- 推荐方式:把
sync.Mutex嵌入目标 struct,所有通过指针访问该 struct 字段的方法都先调用m.Lock() - 避免:在函数参数中传入
*sync.Mutex并期望调用方负责加锁——容易漏、难追踪 - 注意:
sync.RWMutex更适合读多写少场景,但RLock()期间仍不能执行写操作,哪怕写的是不同字段
type Counter struct {
mu sync.RWMutex
val int
}
func (c *Counter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.val++
}
func (c *Counter) Get() int {
c.mu.RLock()
defer c.mu.RUnlock()
return c.val
}
用 sync/atomic 替代指针+Mutex 的简单整数操作
当指针指向的是 int32、int64、uint32、uintptr 或 *T(指针类型)时,sync/atomic 提供无锁原子操作,性能更好、代码更简洁。
但要注意:atomic 只保证单个字段的原子性,不适用于多字段协同更新(比如同时改 x 和 y 并保持一致性)。
- 用
atomic.LoadInt64(p)/atomic.StoreInt64(p, v)替代带锁的读写 - 用
atomic.AddInt64(p, 1)替代*p++这类非原子操作 - 用
atomic.CompareAndSwapPointer(&p, old, new)实现无锁指针替换,比如实现简易版对象池 - 切记:atomic 操作要求指针对齐(通常由 Go 编译器保证),但若结构体内嵌指针并手动计算偏移,可能破坏对齐
指针逃逸与并发生命周期管理常被忽略
Go 编译器会根据逃逸分析决定变量分配在栈还是堆。一旦指针逃逸到堆,它的生命周期就不再受当前函数栈帧约束——这在并发中意味着:goroutine 可能还在用这个指针,而原始 owner 已经返回、变量本该被回收。
这种问题不会直接 panic,但会导致悬垂指针(dangling pointer)语义,表现为读到零值、随机值,或写入已释放内存(极难复现的崩溃)。
- 典型诱因:将局部变量地址传给 goroutine(如
go f(&x)),而x是栈上变量且函数即将返回 - 解决办法:确保被指针引用的对象至少存活到所有 goroutine 结束,常用手段包括
sync.WaitGroup等待、或显式分配在堆上(如用new(T)或&T{}) - 检查逃逸:用
go build -gcflags="-m -l"查看变量是否逃逸;对关键指针路径保持敏感









