解決Go?Json?Unmarshal反序列化丟失數(shù)字精度問題
現(xiàn)象
業(yè)務會使用 id生成器 產(chǎn)生的 分布式唯一ID,長度比較長。代碼反序列化時,出現(xiàn)精度丟失,導致線上故障。

package main
import (
"testing"
"time"
"github.com/bytedance/sonic"
"github.com/stretchr/testify/assert"
)
func TestPrintAttr(t *testing.T) {
amap := map[string]any{
"psm_businessline_ref": map[string]any{
"id": 1691071059696833999,
},
}
amapStr, err := sonic.MarshalString(amap)
assert.Nil(t, err)
t.Log("\n", amapStr)
m1 := make(map[string]any)
err = sonic.UnmarshalString(amapStr, &m1)
assert.Nil(t, err)
}原因
- 反序列化時,對于數(shù)值類型的value,默認會反序列化成
float64類型。 - float64可以存儲的最大整數(shù)是52位尾數(shù)全位1且指數(shù)部分為最大
0x07FEF FFFF FFFF FFFF
(0x001F FFFF FFFF FFFF)16 = (9007199254740991)10
(0x07EF FFFF FFFF FFFF)16 = (9218868437227405311)10
也就是理論上數(shù)值超過9007199254740991(長度=16)就可能會出現(xiàn)精度缺失。
10進制數(shù)值的有效數(shù)字是16位,一旦超過16位大概率會有缺失精度的問題
一般分布式唯一id是20位長度,所以必然出現(xiàn)精度缺失。
參考:
解決方案
使用 json.Decoder 來代替 json.Unmarshal 方法
package main
import (
"testing"
"time"
"github.com/bytedance/sonic"
"github.com/stretchr/testify/assert"
)
func TestPrintAttr(t *testing.T) {
amap := map[string]any{
"psm_businessline_ref": map[string]any{
"id": 1691071059696833999,
},
}
amapStr, err := sonic.MarshalString(amap)
assert.Nil(t, err)
t.Log("\n", amapStr)
rightM := make(map[string]any)
if len(amapStr) > 0 {
de := jsoniter.NewDecoder(bytes.NewReader([]byte(amapStr)))
de.UseNumber()
err := de.Decode(&rightM)
if err != nil {
t.Fatal(err)
}
}
}json.Number本質(zhì)是string,反序列化的時候?qū)?strong>json的數(shù)值轉(zhuǎn)成字符串,而字符串不會有精度丟失問題,所以沒有問題。json.Number如下:
package json // A Number represents a JSON number literal. type Number string

到此這篇關于解決Go Json Unmarshal反序列化丟失數(shù)字精度問題的文章就介紹到這了,更多相關Go Json Unmarshal內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Go使用Gin+mysql實現(xiàn)增刪改查的詳細實例
golang本身沒有提供連接mysql的驅(qū)動,但是定義了標準接口供第三方開發(fā)驅(qū)動,下面這篇文章主要給大家介紹了關于Go使用Gin+mysql實現(xiàn)增刪改查的相關資料,需要的朋友可以參考下2022-12-12
golang中l(wèi)og包自定義輸出日志格式與寫入到文件
這篇文章主要給大家介紹了關于golang中l(wèi)og包自定義輸出日志格式與寫入到文件的相關資料,日志輸出在任何項目中都極其重要,是有助于后續(xù)我們排查解決程序BUG,需要的朋友可以參考下2023-06-06
golang gin 框架 異步同步 goroutine 并發(fā)操作
這篇文章主要介紹了golang gin 框架 異步同步 goroutine 并發(fā)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12

