go语言中json.Unmarshal导致大数字溢出精度问题

目前问题是出现在使用了uint64的雪花算法ID中发生的问题,在解析出数据的时候导致精度丢失。以下demo并不是使用转换为字符串方式解决。 

package main

import (
	"encoding/json"
	"fmt"
)

func main() {

    var myjson string
	myjson = `{"id":9723275009654785}`
	fmt.Println("期望结果:", myjson)

	type myjsonStruct struct {
		Id uint64 `json:"id"`
	}
	//定义的结构体以及类型 就可以直接解析 此时就是正确的数值不会超出精度。在你完全掌控的结构内可以自行定义字段和类型。
	var myjsonStruct1 myjsonStruct
	json.Unmarshal([]byte(myjson), &myjsonStruct1)
	fmt.Println(fmt.Sprintf("%+v", myjsonStruct1)) //{Id:9723275009654785}

	//将输出错误的精度数值 【不定义具体结构体时将超出精度的时候会出现错误数值】因为interface在解析的时候会自动转换类型为float64 当int64等超出float64的时候就会出现精度丢失 因为float64实际上比int64可用范围小。
	var myjsonStruct2 interface{}
	json.Unmarshal([]byte(myjson), &myjsonStruct2)
	fmt.Println(fmt.Sprintf("%+v", myjsonStruct2)) //map[id:9.723275009654784e+15] 转出结果9,723,275,009,654,784 少了一位

	//此时会输出正确的数值【此时不想定义结构体,但是还想保证结果正确考虑这种方式】
	var myjsonStruct3 interface{}
	JsonDecode(myjson, &myjsonStruct3) //map[id:9723275009654785]
	fmt.Println(fmt.Sprintf("%+v", myjsonStruct3))


}

func JsonDecode(data string, v interface{}) error {
	d := json.NewDecoder(strings.NewReader(data))
	d.UseNumber()
	err := d.Decode(v)
	if err != nil {
		return err
	}
	return nil
}

go语言中json.Unmarshal导致大数字溢出精度问题_第1张图片

总结描述:

1.使用结构体时是正确的结果。因为结构体中类型由明确的定义,此时json.Unmarshal不会统一对数字使用float64类型,就不会存在转换错误的情况

2.使用interface时在出现大数字的情况下例如16位以上的数字可能会出现精度丢失问题。因为此时json.Unmarshal使用了float64

3.使用json.NewDecoder是正确的。为了方便使用上述进行了封装。原理可能是转为字符串实现的。

4.也可以考虑使用json.Number。本质就是一个字符串,只不过是后面你可以自由转换类型

5.自己通过正则将所有数字转为字符串后再json.Unmarshal

目前我需要数字所以选择了简单的处理办法,使用自己封装的JsonDecode方式进行实现。

 

你可能感兴趣的:(后端,笔记,数据库,golang,json,开发语言,算法)