推荐用十进制字符串序列化*big.int:调用text(10)写入,setstring(s,10)读取并检查返回bool;需注意换行符处理;二进制方案需手动保存符号位与空切片特判;避免使用gob因其不跨语言、不向后兼容且不可读。

Go 中 *big.Int 不能直接用 json.Marshal 或 gob.Encoder 默认序列化
因为 *big.Int 是结构体指针,内部字段(如 abs、neg)未导出,json 包无法访问;gob 虽支持,但需显式注册且跨语言不兼容。直接写二进制或字符串是更可控的选择。
推荐方式:写入十进制字符串(最安全、可读、跨平台)
这是绝大多数场景的首选——人类可读、无精度损失、无字节序/平台依赖、易于调试和人工检查。
- 用
bigInt.Text(10)获取十进制字符串,再写入文件 - 读取时用
new(big.Int).SetString(s, 10)恢复,返回(*big.Int, bool),务必检查bool是否为true - 注意:字符串末尾可能带换行符,写入时建议用
fmt.Fprintln或手动加\n,避免多行错位
file, _ := os.Create("bigint.txt")
defer file.Close()
_, _ = fmt.Fprintln(file, bigInt.Text(10)) // 自动换行
需要紧凑存储?用 big.Int.Bytes() 写二进制,但注意符号处理
Bytes() 只返回**绝对值**的补码字节数组(大端),不包含符号信息。负数会被截断为正数表示,直接写会丢符号。
- 写入前必须单独保存符号:用
bigInt.Sign()(返回 -1/0/1) - 推荐组合格式:1 字节符号 + 剩余字节(
bigInt.Abs().Bytes()) - 读取时先读符号字节,再读字节数组,最后用
new(big.Int).SetBytes()并根据符号调用Neg() - 注意:
Bytes()返回的切片不含前导零,但若值为 0,返回空切片[]byte{},需特殊处理(比如约定空切片表示 0)
别用 gob 直接编码 *big.Int —— 兼容性差且隐式依赖
gob 确实能编码 *big.Int(它实现了 GobEncoder 接口),但存在几个硬伤:
- 生成的二进制格式不向后兼容:Go 版本升级可能导致旧数据无法解码
- 完全不可跨语言:Python/JS 等无法解析 gob 流
- 文件内容不可读,调试困难;一次写错就难恢复
- 如果结构体里嵌套了
*big.Int字段,gob会递归编码,但依然受限于上述问题
除非你 100% 确定只在同版本 Go 进程间传递且永不导出,否则不值得冒这个风险。
真正麻烦的地方不在写入动作本身,而在「如何让读取方明确知道当前字节流的编码意图」——字符串格式靠内容自解释,二进制格式必须靠协议头或文档约定。漏掉符号、混淆空值、忽略错误返回,这三个点最容易导致线上静默失败。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











