big.NewInt 只能传入 int64 范围内的整数,因其参数类型固定为 int64;超大数须用 new(big.Int).SetString(),且必须检查返回的布尔值以确保解析成功。

直接说结论:big.NewInt 只能传入 int64 范围内的整数字面量或变量,不能传字符串、uint64、浮点数,也不能传超 64 位的十进制大数——想创建任意长度的大整数,得用 new(big.Int).SetString()。
为什么 big.NewInt 不能直接创建超大整数?
因为它的函数签名是 func NewInt(n int64) *Int,参数类型死锁在 int64。哪怕你写 big.NewInt(100000000000000000000),Go 编译器也会先尝试把字面量解析成 int64,超出范围就报错:constant 100000000000000000000 overflows int64。
常见误用场景:
- 从 JSON 或用户输入读到字符串
"123456789012345678901234567890",直接塞给NewInt—— 编译不过 - 用
uint64变量(比如时间戳纳秒值)调用,如big.NewInt(myUint64)—— 类型不匹配,需显式转换(且可能溢出) - 以为
NewInt(0)返回的是“零值对象”,其实它返回的是可安全复用的指针,但内部值是 0 —— 这点没问题,但别误以为它支持初始化为 nil
big.NewInt 的正确使用场景和限制
它只适合快速构造小整数(≤ 2⁶³−1)、做临时计算起点,比如计数器初始化、小常量参与运算。不是为“大整数”而设计的入口函数,而是为“从机器整数转为 *big.Int”服务的便捷封装。
立即学习“go语言免费学习笔记(深入)”;
关键事实:
-
big.NewInt(0)和big.NewInt(1)是最常用写法,安全、高效 - 传负数合法:
big.NewInt(-42)→ 值为 -42 的*big.Int - 传
int32/int等更小类型会自动提升,没问题;但uint64必须强转:big.NewInt(int64(x)),且要自己确保x ≤ math.MaxInt64 - 性能上无额外开销——它只是分配一个
*big.Int并设置abs和neg字段,比SetString快一个数量级
真正创建任意长度大整数:用 SetString 替代
当你要处理来自外部(文件、网络、命令行)的超长数字字符串时,唯一可靠方式是先创建空 *big.Int,再调用 SetString:
num := new(big.Int)
_, ok := num.SetString("123456789012345678901234567890", 10)
if !ok {
log.Fatal("invalid number string")
}
注意点:
-
SetString第二个参数是进制,十进制填10,十六进制填16(支持带0x前缀) - 返回布尔值表示是否成功解析,**必须检查**,否则静默失败(比如空字符串、含空格、非法字符)
- 可以复用同一个
*big.Int实例多次调用SetString,避免频繁分配 - 如果字符串带符号(如
"-999..."),SetString自动识别,无需额外处理
最容易被忽略的是:很多人以为 big.NewInt 是“大整数的起点”,结果卡在编译错误里半天。其实 Go 的设计很明确——NewInt 是“小整数升格”,SetString 才是“任意精度载入”。混用或跳过错误检查,基本就是后续计算出错的伏笔。


















