不要将带有 int64 的数据反序列化到 map[string]interface{} 中

我们知道,在 Go 语言中,有一种 map 数据类型,当我们需要向哈希表中存入不确定类型的数据时,我们可能会用到 map[string]interface{}

m1 := make(map[string]interface{}, 0)
m1["name"] = "user1"
m1["age"] = 21
m1["weight"] = 130.5

当向其中存储一些数据后,当我们遍历它,就能拿到自己想要的结果:

for k, v := range m1 {
	fmt.Printf("%s-%s\n", k, v)
}

我们再看复杂一点的示例,服务 a,调用服务 b,获取用户信息。

服务 b 返回 json 给服务 a:{"name": "user1","userId":3,"orgId":202505060582035456}

// 服务 a 得到用户信息
// 经过服务内部的接口通讯,会对数据 json 序列化和反序列化:
json1 := `{"name": "user1","userId":3,"orgId":202505060582035456}`
m1 := make(map[string]interface{}, 0)
json.FromJson(json1, &m1)
for k, v := range m1 {
	fmt.Printf("%s-%s\n", k, v)
}
t.Log(json.ToJsonIgnoreError(m1))

使用 map[string]interface{} 数据接受 json 数据,会使得数值类型的数据被默认为 float64 类型。

在上面的遍历过程中,我们可能会发现,在 for 语句体中,orgId 对应的值被默认为 float64 类型,这是 go 语言内部的机制,先不予讨论。

这里要说的是在这种情况下,会出问题,因为 float64 不能存放 int64 的最大值,到了一定的情况下,会损失精度。上述示例中,便利得到的 orgId 值为 202505060582035460,和原始的 202505060582035456 不一致,此时就会导致比较严重的问题,比如查询用户企业查询不到等。

要解决这个问题,办法有多种,比如我们可以让,数据反序列化到结构体中:

type User struct {
	Name     string `json:"name"`
	UserId   int64  `json:"userId"`
	OrgId    int64  `json:"orgId"`
}
user := User{}
json.FromJson(json1, &user)
posted @ 2021-03-06 12:54  suhanyujie  阅读(269)  评论(0编辑  收藏  举报