在 Golang 的 JSON 序列化过程中,遇到除数为零的情况可能会导致返回 Inf
(无穷大)。这是 Golang 实现了 IEEE 754 标准的结果,当除数在运行时动态为零时,返回的是 +Inf
或 -Inf
,而不是 panic。但这种情况在 JSON 序列化时,Inf
值会触发错误:
json: unsupported value: +Inf
问题分析:Golang 运行时的除零出现 Inf
在 Golang 中,浮点数运算时,如果除数为零,会按照 IEEE 754 标准返回无穷大(+Inf
或 -Inf
)。这种行为虽然符合浮点数标准,但在序列化为 JSON 时会导致 Golang 返回错误,特别是当这些 Inf
值包含在结构体中。
例如,在下面的代码中,如果运行时的除数变为零,结果为 +Inf
,会导致 JSON 序列化失败。
package main
import (
"encoding/json"
"fmt"
"strconv"
)
func interfaceToFloat64(unk interface{}) (result float64) {
switch i := unk.(type) {
case float64:
result = float64(i)
case float32:
result = float64(i)
case int64:
result = float64(i)
case int32:
result = float64(i)
case int:
result = float64(i)
case uint32:
result = float64(i)
case uint64:
result = float64(i)
case uint:
result = float64(i)
case string:
result, _ = strconv.ParseFloat(i, 64)
default:
result = 0.0
}
return
}
func main() {
var (
a interface{} = 1
b interface{} = 0
)
x := interfaceToFloat64(a) / interfaceToFloat64(b)
fmt.Println("x:", x) // 输出:+Inf
type T struct {
F float64
}
t := T{F: x}
_, err := json.Marshal(t)
fmt.Println("err:", err) // 输出:json: unsupported value: +Inf
}
解决方案:避免 JSON 序列化时的 Inf
值
为了防止在序列化时发生 Inf
或 NaN
错误,可以在序列化前对浮点数进行检查,检测并处理这些特殊值。
Golang 提供了 math
包中的方法 IsNaN
和 IsInf
,可以用于判断浮点数是否为 NaN
或 Inf
。
import (
"math"
)
// 处理浮点数
if math.IsNaN(x) || math.IsInf(x, 0) {
x = 0.0 // 或者选择其他值如 null
}
通过这样的检测,可以确保在 JSON 序列化之前,将特殊的 NaN
和 Inf
转换为有效值,避免 JSON 序列化失败。
实践中的应用
为了更方便地处理包含浮点数的结构体,可以封装一个通用的函数,将这些结构体在序列化前处理:
package main
import (
"encoding/json"
"fmt"
"math"
)
type T struct {
F float64
}
func safeMarshal(v interface{}) ([]byte, error) {
// 遍历结构体中的浮点数并处理
if t, ok := v.(*T); ok {
if math.IsNaN(t.F) || math.IsInf(t.F, 0) {
t.F = 0.0 // 可以根据需要设置默认值
}
}
return json.Marshal(v)
}
func main() {
x := math.Inf(1) // +Inf
t := T{F: x}
// 使用 safeMarshal 函数进行序列化
data, err := safeMarshal(&t)
if err != nil {
fmt.Println("JSON 序列化错误:", err)
} else {
fmt.Println("JSON 序列化结果:", string(data))
}
}
JSON 序列化的其他考虑
- NaN 的处理:NaN 是另一种需要特别处理的特殊值。类似
Inf
,NaN
在 JSON 序列化时也会触发错误。因此,建议同时处理这两种情况。 - API 返回格式:当 API 返回的浮点数计算涉及可能产生
NaN
或Inf
的场景时,最好提前处理这些特殊值,以免引发客户端解析错误。常见的处理方法包括将这些值设置为零或返回null
,具体取决于业务需求。
参考文档
FAQ
为什么在 Golang 中除数为零会返回
Inf
? 根据 IEEE 754 标准,浮点数除以零的结果会是+Inf
或-Inf
,这是浮点数运算的一种定义,而非程序的错误。如何处理 JSON 序列化时的
Inf
值? 在 JSON 序列化之前,可以使用math.IsNaN
和math.IsInf
检测并替换这些特殊值,避免序列化失败。什么是
NaN
和Inf
?NaN
代表“非数字”(Not a Number),常见于非法数学操作的结果,如0/0
。Inf
则表示无穷大,通常出现在除数为零时。