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

Golang中结构体内部big.Int调用Exp后值异常变更问题

问题:值拷贝 big.Int 后调用 Exp 方法,原变量意外被修改
type Decimal struct {
    c big.Int // coefficient
    q big.Int // exponent
}
a := big.NewInt(1)
b := big.NewInt(2)
d := Decimal{*a, *b}
d.c.Exp(big.NewInt(11), big.NewInt(2), big.NewInt(0))
fmt.Println(a, b, d) // 输出:11 2 {{false [121]} {false [2]}}

构造 Decimal 实例 d 时已通过 *a 完成值拷贝,修改 d.c 后,原变量 a 的值却变成了 Exp 方法第一个参数的值,预期 a 应保持不变。补充:打印 a、b、d.c、d.q 的指针地址,发现前后均不相同。


原因与解决办法

原因

这是 Go 标准库 big.Int 的内存复用优化导致的:
当调用 x.Exp(y, z, m) 时,如果参数 y 是临时创建的 big.Int(比如代码中的 big.NewInt(11)),标准库会直接复用 y 的底层数组存储计算结果,减少内存分配开销。

而 big.NewInt 会缓存一些小整数对应的 big.Int 实例(比如 1、11 这类),a := big.NewInt(1) 得到的指针,指向的正是缓存中的某个实例。当 Exp 方法复用临时变量 big.NewInt(11) 的底层内存时,恰好覆盖了缓存中 a 指向的那个实例的值,最终导致打印 a 时看到被修改后的结果。

虽然你对 a 做了值拷贝给 d.c,但 a 本身是指向缓存实例的指针,缓存实例被修改后,a 的输出自然跟着变。

解决办法

  • 方法一:绕开 big.NewInt 的缓存,用 SetInt64 创建独立实例:
    a := new(big.Int).SetInt64(1)
    
  • 方法二:确保 d.c 和 a 指向的实例完全隔离,拷贝时显式分配新内存:
    d := Decimal{*new(big.Int).Set(a), *b}
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:12:37