go中大数计算必须用math/big方法,不可用常规操作符;big.int需用newint或setstring初始化,运算须调用add、sub等方法且多为原地修改,比较用cmp,幂运算统一用exp。

Go 里大数计算不能用 +、*、== 这些操作符,必须调 math/big 提供的方法;否则编译失败或结果静默错误——这是最常踩的坑,也是你看到负数、零值、panic 的根本原因。
big.Int 初始化必须用 SetString 或 NewInt,不能写字面量
你不能写 var x *big.Int = 123456789012345678901234567890,Go 会把它当 int 或 int64 处理,超限直接截断或编译报错。正确方式只有两种:
-
big.NewInt(n):仅支持int64范围内的整数(≤ 9223372036854775807) -
new(big.Int).SetString(s, base):处理任意长度字符串,base必须显式传(如十进制传10,十六进制传16);"0xabc"要么去前缀后传16,要么留前缀但传0(只认小写0x,不认0X或空格) - 字符串首尾空白会导致
SetString返回false,务必先strings.TrimSpace()
所有运算都得用方法链,且多数是原地修改
big.Int 没有运算符重载,a + b 会报 invalid operation: a + b (operator + not defined on *big.Int)。加减乘除必须用 Add、Sub、Mul、Div 等方法,而且注意签名:
-
z.Add(x, y)表示把x + y的结果存进z,z原值被覆盖(不是“返回新对象”) - 想保留
x和y?得手动复制:z.Set(x).Add(z, y),因为big.Int没有内置Clone() - 链式调用可行:
new(big.Int).Mul(a, b).Add(c, d),但要清楚每一步改的是哪个变量 - 比较必须用
Cmp()(返回-1/0/1),别写x == y或x.Cmp(y) == 0(后者虽能用,但低效)
Exp 是唯一幂运算入口,模幂和普通幂共用一个方法
Go 没有 Pow 函数,只有 (*big.Int).Exp(x, y, m)。它同时支持普通幂和模幂,靠第三个参数 m 控制:
-
m == nil或m.Sign() == 0→ 计算x^y(无模) -
m != nil && m.Sign() != 0→ 计算x^y mod |m|(自动取绝对值) -
y必须是非负整数,y 时结果恒为 <code>1(模意义下也是1 mod |m|) - 底数
x可为负,但指数过大时仍可能耗尽内存,建议对y.BitLen()做上限校验
性能关键:避免 new(big.Int) 频繁分配
每次 new(big.Int) 都触发堆分配,高频场景(比如循环内多次计算)下 GC 压力明显,实测比复用慢 3–5 倍。正确做法是:
- 声明局部变量复用:
var tmp big.Int,然后反复调tmp.Add(x, y)、tmp.Set(nil)清空 - 不要写
z := new(big.Int); z = big.NewInt(42)—— 前面的z指针泄漏了 - 转字符串优先用
x.Text(10),比x.String()更快更稳定;Text()支持 2–36 进制,String()固定十进制 - JSON 序列化需自定义:标准库不支持直接 encode
*big.Int,通常转成字符串再塞进 map;解码时先读字符串,再用SetString()
真正容易被忽略的是所有权和内存复用逻辑:你写的不是“值”,而是一组指向底层 uint 数组的指针,方法调用是否修改原值、是否需要提前拷贝、是否该复用对象——这些不看文档很容易写出内存泄漏或静默错误的结果。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











