网站中怎么做图片的变换,东莞市义务教育阶段统一招生平台,非交互式网站备案,昆明做网站建设哪家好【Golang】Json 无法表示 float64 类型的 NaN 以及 Inf 导致的 panic 
原因 
golang 服务出现了 panic#xff0c;根据 panic 打印出的堆栈找到了问题代码#xff0c;看上去原因是#xff1a;json 序列化时#xff0c;遇到了无法序列化的内容 
[panic]: json: unsupported …【Golang】Json 无法表示 float64 类型的 NaN 以及 Inf 导致的 panic 
原因 
golang 服务出现了 panic根据 panic 打印出的堆栈找到了问题代码看上去原因是json 序列化时遇到了无法序列化的内容 
[panic]: json: unsupported value: NaN or InfiniteNaN 以及 Infinite 
解释基本可以判断出NaN 以及 Inf 是 float64 类型的两种特例Json 无法表示这类数据故 panic 
深度剖析 
查阅 log 看到这里最原始的 NaN 其实是字符串NaN,明明是字符串是如何将 NaN转变为 float64 的呢问题出在使用的 cast 包的 ToFloat64上  可以从 ToFloat64 的源码中看到当需要转换成 float64 的类型是 string 或者 json.Number 时调用的都是 strconv.ParseFloat 函数s.Float64 本质也是调用该函数继续阅读 strconv.ParseFloat我们可以在strconv/atof.go文件中看到以下代码strconv.ParseFloat 会将字符串 NaN 以及 Inf 转换为 float64 类型的 NaN 以及 Inf。 而 json 无法处理这两种数据会直接 panic 
修复 
单独判断下即可 
func SetValWhenFloatIsNaNOrInf(val float64) float64 {if math.IsNaN(val) {return 0.00}if math.IsInf(val, 0) {return 100.00}return val
}扩展 
NaN 和 Inf 怎么来的呢  在 float64 类型中我们可以通过 zero/zero 来得到 NaN也可以用过 除零 操作来得到 Inf在 Google 并没有得到能解释这两种常量存在的原因只从二进制浮点数算术标准IEEE 754看到有相关的定义 能否把 NaN 以及 Inf 作为 map 的 key 测试代码 
func TestNaNKeyMap() {m : make(map[float64]struct{}, 0)for i : 0; i  10; i {m[math.NaN()]  struct{}{}fmt.Printf(nan map len:%d\n, len(m))}
}
func TestInfKeyMap() {m : make(map[float64]struct{}, 0)for i : 0; i  10; i {m[math.Inf(0)]  struct{}{}fmt.Printf(inf map len:%d\n, len(m))}
}结果可以看待对于 NaN每次赋值的时候其实都是给不同的 key 赋值而 Inf 则不是所以我们可以得出以下结论map[float64]struct 这种以 float64 为 key 的 map存在内存泄漏的可能  map 的 key 都会经过 hash然后再确定value 存储的位置那么问题大概率出在 hash 算法上在 runtime/alg.go 找到以下函数 可以看到算法里判断到 f ! f 时会给hash 值增加一个随机数并且注释里也说了是为了适配 any kind of NaN 这里 f ! f 的判断也同时用在 func IsNaN(f float64) (is bool) 函数中。