当前位置:

首页 > 编程开发 > 详解Go语言中json转换int64精度丢失的问题解决

详解Go语言中json转换int64精度丢失的问题解决

GoldWave 简体中文
GoldWave 简体中文

一款功能相当强大的录音及音频编辑软件,不仅可以编辑音频,而且还可以录音,功能丰富,操作简单,使用方便,实用性强,并且占用电脑内存小,运行速度快,不卡顿电脑,使电脑系统保持良好的运行状态。支持许多格式的音频文件,包括WAV、OGG、VOC、IFF、AIFF、

立即下载
2026-08-22
图形多媒体 音频工具 GoldWave 视频渲染 制作软件 goldwave教程

Go语言JSON解析默认将数字转为float64,导致大整数精度丢失。可通过json.Number暂存原始文本、json:",string"标签自动转换或自定义UnmarshalJSON方法解决,三种方案分别适用于不同场景。

Go语言里处理JSON转int64的时候,有个细节特别容易让人踩坑——精度丢失。这事儿说大不大,但一旦碰上,排查起来还挺头疼的。原因其实不复杂:JSON标准里根本没有专门定义整数类型,它用double(双精度浮点数)来兜底所有数字。而float64在表示超大整数时,天然就存在精度瓶颈。

详解Go语言中json转换int64精度丢失的问题解决

导致精度丢失的情况

通常来说,下面这几种情况最容易中招:

1. 大整数:如果JSON里的数字超出了int64的范围(-2^63 到 2^63-1),转换时精度说丢就丢。

2. 浮点数:如果数字本身带小数,强转成int64时,小数点后面的部分自然会被截掉。

3. 负数:和正数一样,一旦超过表示范围,同样逃不掉精度损失。

解决方法

那么,怎么避开这个坑呢?有几种常见的做法。

1. 使用 json.Number 类型

解析JSON时,用json.Number这个类型来“暂存”原始的数字文本,之后再按需转成int64。这个方法的关键在于延迟了类型转换,从而保留了原始精度。

import (
    "encoding/json"
    "fmt"
    "math/big"
)
func main() {
    jsonStr := `{"number": "9223372036854775808"}` // 超出int64范围的数字
    var data map[string]json.Number
    err := json.Unmarshal([]byte(jsonStr), &data)
    if err != nil {
        panic(err)
    }
    number := data["number"]
    num := new(big.Int)
    num, ok := number.Int64()
    if !ok {
        num, _ = new(big.Int).SetString(string(number), 10)
        fmt.Printf("转换为big.Int: %s\n", num.String())
    } else {
        fmt.Printf("转换为int64: %d\n", num)
    }
}

2. 使用第三方库

像go.mongodb.org/mongo-driver/bson这类库,内置了更灵活的整数处理机制,有时候能直接解决问题。

3. 手动预处理

在调用JSON解析之前,先手动检查数字大小。一旦发现超出int64范围,可以提前做特殊处理。

4. 约定JSON格式

如果JSON数据由你控制,那就从源头约定好:确保所有数字都在int64的安全范围内,或者直接约定用字符串来表示大整数。

jsoniter "github.com/json-iterator/go"
func Test0008_Jsoniter_Marshal(t *testing.T) {
    order := Order{
       Id:         baseutils.SnowflakeNextVal(),
       OrderId:    "12345678",
       Money:      99.99,
       CreateTime: time.Now(), // 2023-12-05T16:19:33.943989108+08:00
       Extend:     map[string]string{"name": "张三"},
    }
    // 使用1:直接转成字符串
    jsonStr, _ := jsoniter.MarshalToString(order)
    fmt.Println("jsonStr:", jsonStr)
    // 使用2:直接转成字节数组
    jsonByteArr, _ := jsoniter.Marshal(order)
    fmt.Println("jsonByteArr:", jsonByteArr)
    // 使用3:反序列化之字符串转结构体
    str := `{"id":666, "order_id":"12345678", "money": 99.99, "create_time":"2023-12-05T16:19:33.943989108+08:00", "extend":{"name":"张三"}}`
    var order2 Order
    err := jsoniter.UnmarshalFromString(str, &order2)
    if err != nil {
       fmt.Println("err2:", err)
    }
    fmt.Println("order2:", order2)
    // 使用4:反序列化之字节数组转结构体
    var order3 Order
    var jsonNew = jsoniter.ConfigCompatibleWithStandardLibrary
    // 自适应类型
    extra.RegisterFuzzyDecoders()
    err = jsonNew.Unmarshal(jsonByteArr, &order3)
    if err != nil {
       fmt.Println("err3:", err)
    }
    fmt.Println("order3:", order3)
}
​​​​​​​order3: {572839995925069824 12345678 99.99 2024-04-29 17:41:37.8819085 +0800 CST map[name:张三]}

知识扩展

说白了,Go里JSON转换int64精度丢失这个问题的根子,就在encoding/json默认把JSON数字解析成float64上。float64只能精确表达±2^53以内的整数,一旦越界,精度就开始打折扣了。

业内针对这个问题,主要有三种比较成熟的方案。每个方案各有侧重,你可以根据实际场景来选。

方案一:使用 json.Number (最轻量、最精准)

这个方案的核心思路是“延迟转换”。把可能包含大整数的字段声明为json.Number类型,它本质上就是个字符串,只负责暂存原始数字文本。之后你有需要了,再手动调用.Int64()方法拿到精确的int64值。

package main
import (
	"encoding/json"
	"fmt"
)
type MyData struct {
	// 将可能超限的整数字段声明为 json.Number
	LargeID json.Number `json:"id"`
}
func main() {
	jsonStr := `{"id": 9223372036854775807}`
	var data MyData
	if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
		panic(err)
	}
	// 安全地将 json.Number 转换为 int64
	id, err := data.LargeID.Int64()
	if err != nil {
		panic(err) // 处理转换错误
	}
	fmt.Printf("转换后的 int64 值: %d\n", id)
}

关键点: json.Number字段必须手动调用.Int64()方法,这个步骤不能省,否则拿不到精确值。

方案二:使用 json:",string" 标签 (最优雅、最常用)

这个方案利用结构体标签,让encoding/json在编解码时自动完成JSON字符串和Go数值之间的双向转换。尤其适合前端(比如Ja vaScript)只接收字符串的场景。

package main

import (
	"encoding/json"
	"fmt"
)

type MyData struct {
	// 使用 json:",string" 标签,让 ID 在 JSON 中以字符串形式传递
	LargeID int64 `json:"id,string"`
}

func main() {
	jsonStr := `{"id": "9223372036854775807"}`
	var data MyData
	if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
		panic(err)
	}
	fmt.Printf("Unmarshal 得到的 int64 值: %d\n", data.LargeID)
}

方案三:自定义 UnmarshalJSON 方法 (终极可控)

这种方案通过实现json.Unmarshaler接口,让你完全掌控自定义类型的解析过程。你可以把解析逻辑封装成独立类型,然后在需要的地方复用。

package main

import (
	"encoding/json"
	"fmt"
	"strconv"
)

// 定义一个新的类型,并为其实现 UnmarshalJSON 接口
type PreciseInt int64

func (pi *PreciseInt) UnmarshalJSON(b []byte) error {
	// 1. 先解析到 json.Number
	var n json.Number
	if err := json.Unmarshal(b, &n); err != nil {
		return err
	}
	// 2. 再从 json.Number 安全地转换为 int64
	i, err := n.Int64()
	if err != nil {
		return err
	}
	*pi = PreciseInt(i)
	return nil
}

type MyData struct {
	LargeID PreciseInt `json:"id"`
}

func main() {
	jsonStr := `{"id": 9223372036854775807}`
	var data MyData
	if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
		panic(err)
	}
	fmt.Printf("转换后的 int64 值: %d\n", data.LargeID)
}

方案对比与选择建议

为了帮你做个更直观的判断,这里整理了张对比表:

对比维度方案一:json.Number方案二:json:",string" 标签方案三:自定义 UnmarshalJSON
核心机制使用 json.Number 类型暂存原始 JSON 数字字符串利用标签 ,string 实现 JSON 字符串与 Go 数值的自动转换为自定义类型实现 json.Unmarshaler 接口,完全掌控解析过程
代码侵入性低:只需修改结构体字段类型低:只需在结构体标签中添加 ,string中等:需要定义新类型并实现接口
对前端的影响无:前端接收到的仍是 Number有:前端需处理 string 类型可控:可根据实现逻辑决定 JSON 中的格式
性能开销中等:涉及额外类型转换,有约 2-3 倍开销低:性能损耗极小中等:类似 json.Number,取决于实现
灵活性与扩展性低:功能相对单一低:功能单一极高:可根据需求定制任意逻辑
推荐场景处理动态结构或第三方 API 的 JSON 数据时与Ja vaScript 前端交互时的首选方案需要对特定字段进行复杂校验、转换或类型限制时

总结一下:

  • 和前端(尤其是Ja vaScript)打交道,方案二 (json:",string" 标签) 最直接、最优雅。
  • 如果遇到结构不固定的JSON数据,方案一 (json.Number) 的灵活性是最好的。
  • 要是前两个都满足不了你的特殊需求,方案三 (自定义UnmarshalJSON) 能给你终极的掌控感。
本文内容来源于网友投稿,如有侵权请联系删除。
作者最新文章
编程开发
相关文章 更多
解决PHP递归报错:max_nesting_level限制与内存溢出处理
解决PHP递归报错:max_nesting_level限制与内存溢出处理

遇到PHP递归报错时,不要盲目调大max_nesting_level。本文教你区分Xdebug限制、内存耗尽和正则递归错误,提供代码级的终止条件优化与迭代替代方案,彻底解决栈溢出问题。

PHP递归中static变量与引用传递的常见陷阱及调试
PHP递归中static变量与引用传递的常见陷阱及调试

本文分析PHP递归中static变量导致的状态污染及引用传递引发的共享数据修改问题。提供具体的代码复现、缓存键设计建议及调试打印技巧,帮助开发者避免隐蔽的逻辑错误。

PHP递归性能优化技巧与迭代替代方案
PHP递归性能优化技巧与迭代替代方案

解析PHP递归函数在树形数据处理中的性能瓶颈,提供预加载数据消除I/O、使用显式栈替代深层递归的实战方案,帮助开发者在代码可读性与执行效率间做出合理取舍。

Java测试中怎么使用Mockito模拟依赖对象
Java测试中怎么使用Mockito模拟依赖对象

详细讲解在Java单元测试中如何使用Mockito模拟依赖对象,包括引入依赖、创建Mock、打桩返回值、行为验证以及Mock与Spy的核心差异和常见陷阱排查。

链表删除节点的时间复杂度是多少及其详细分析
链表删除节点的时间复杂度是多少及其详细分析

详细分析链表删除节点的时间复杂度,深入探讨单链表与双向链表在不同已知前提下的查找与删除开销,并结合完整代码与清晰图解进行对比总结。

codex如何配置模型参数及文件设置教程
codex如何配置模型参数及文件设置教程

想知道如何让AI写出的代码更贴合你的习惯?本文手把手教你在VS Code中调整Codex相关模型参数,通过修改配置文件优化温度值和令牌限制,解决代码建议不准确或响应慢的问题。

Claude Code AI编程工具实力揭秘与编程助手实测
Claude Code AI编程工具实力揭秘与编程助手实测

通过实测展示Claude Code在终端中如何理解自然语言指令、自动修改代码文件并处理复杂编程任务,帮助开发者评估其实际辅助能力。

winforms教程自学入门与基础开发步骤详解
winforms教程自学入门与基础开发步骤详解

本教程详细讲解如何使用Visual Studio创建WinForms项目,通过添加按钮和标签控件并编写点击事件代码,实现一个基础的计数器功能,适合C#初学者快速上手Windows窗体应用开发。

Cursor自动补全设置教程教你快速开启代码补全功能
Cursor自动补全设置教程教你快速开启代码补全功能

详解Cursor编辑器中自动补全功能的开启与优化设置,涵盖Tab触发机制、上下文窗口调整及模型切换,帮助开发者解决补全延迟、干扰大等问题,提升编码流畅度。

pandas的数据格式怎么转换和设置方法教程
pandas的数据格式怎么转换和设置方法教程

详解Pandas中数据格式转换的核心方法,包括astype强制转换、to_numeric容错处理及日期解析技巧,解决常见类型错误并提升数据处理效率。

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件
macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

Mac软件 更多
photoshop
photoshop
Windows、macOS 、 iPad

Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。

Blender
Blender
Windows、macOS 和 Linux

Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

灵活计算器
灵活计算器
macOS/iOS/Android

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

WINDOWS 更多
3dmax(3ds max)
3dmax(3ds max)
Windows

Autodesk 3ds Max 是一款专业的三维建模、动画与渲染软件,广泛应用于建筑可视化、游戏开发、影视动画、广告设计和产品展示等领域。

photoshop
photoshop
Windows、macOS 、 iPad

Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。

Blender
Blender
Windows、macOS 和 Linux

Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

即将离开本站
您即将前往第三方网站,请确认是否继续?