atomic.AddInt64必须传指针,因其函数签名要求int64类型参数以直接操作内存地址,传值会编译报错“cannot use x as int64”,且变量须可寻址、8字节对齐,否则32位平台可能panic。

atomic.AddInt64 为什么必须传指针?
因为原子操作直接在内存地址上执行硬件级指令,atomic.AddInt64 的第一个参数类型是 *int64,传值会导致操作失效——它改的是副本,不是原始变量。
- 错误写法:
atomic.AddInt64(counter, 1)(编译报错:cannot use counter (type int64) as type *int64) - 正确写法:
atomic.AddInt64(&counter, 1) - 常见坑:局部变量取地址后逃逸到堆,但更危险的是忘记加
&导致编译失败或误用非原子操作
atomic.Value 存结构体时类型必须一致
atomic.Value 允许存任意类型,但每次 Store 和 Load 必须是同一具体类型,否则运行时报 panic:“invalid memory address or nil pointer dereference” 或更隐蔽的类型断言失败。
- 安全用法:先
Store(&MyStruct{}),后续只能Load().(*MyStruct) - 危险操作:第一次
Store(&A{}),第二次Store(&B{}),再Load().(*A)→ panic - 建议封装:用私有字段 + 方法隐藏类型断言,避免裸露
.(*T)
CompareAndSwap 失败不等于出错,要检查返回值
atomic.CompareAndSwapInt32 等 CAS 操作返回 bool,表示“旧值匹配且已更新”。很多开发者忽略返回值,以为调用即成功,结果逻辑跳过、状态卡死。
- 典型场景:实现一次性初始化(类似
sync.Once底层) - 必须写成:
if atomic.CompareAndSwapInt32(&done, 0, 1) { /* 执行初始化 */ } - 漏掉
if直接执行初始化代码 → 多次触发,破坏幂等性
int32 和 int64 在 32 位系统上的原子性差异
Go 要求原子操作的目标变量对齐且尺寸适配 CPU 原子指令能力。int64 在 32 位系统上无法保证单指令原子性,Go 运行时会退化为锁保护——这会隐式引入性能回退,且 -race 检测不到问题。
立即学习“go语言免费学习笔记(深入)”;
- 安全选择:优先用
int32或atomic.Int32(Go 1.19+ 类型安全封装) - 若必须用 64 位计数器:确保部署环境是 64 位 OS + CPU,或改用
sync.Mutex显式保护 - 验证方式:在目标架构上跑
go test -race,并观察是否出现 unexpected lock contention
实际写的时候,最容易被忽略的是类型一致性与指针传递这两个硬约束——它们不报运行时错误,但要么编译不过,要么行为完全偏离预期。



















