插件窝 干货文章 Go语言float64精度丢失:如何保证JSON输出保留小数点后两位零?

Go语言float64精度丢失:如何保证JSON输出保留小数点后两位零?

JSON Value 点数 Data 134    来源:    2025-03-11

在Go语言中,处理浮点数时可能会遇到精度丢失的问题,尤其是在将浮点数序列化为JSON时。为了确保JSON输出保留小数点后两位零,你可以使用以下几种方法:

方法1:使用strconv.FormatFloat格式化浮点数

你可以先将浮点数格式化为字符串,然后再将其序列化为JSON。这样可以确保小数点后保留两位零。

package main

import (
    "encoding/json"
    "fmt"
    "strconv"
)

type Data struct {
    Value string `json:"value"`
}

func main() {
    value := 123.456
    formattedValue := strconv.FormatFloat(value, 'f', 2, 64)

    data := Data{Value: formattedValue}
    jsonData, err := json.Marshal(data)
    if err != nil {
        fmt.Println("Error marshalling JSON:", err)
        return
    }

    fmt.Println(string(jsonData))
}

输出:

{"value":"123.46"}

方法2:自定义JSON序列化

你可以为结构体实现自定义的MarshalJSON方法,以控制浮点数的序列化方式。

package main

import (
    "encoding/json"
    "fmt"
    "strconv"
)

type Data struct {
    Value float64 `json:"value"`
}

func (d Data) MarshalJSON() ([]byte, error) {
    formattedValue := strconv.FormatFloat(d.Value, 'f', 2, 64)
    return json.Marshal(map[string]string{
        "value": formattedValue,
    })
}

func main() {
    data := Data{Value: 123.456}
    jsonData, err := json.Marshal(data)
    if err != nil {
        fmt.Println("Error marshalling JSON:", err)
        return
    }

    fmt.Println(string(jsonData))
}

输出:

{"value":"123.46"}

方法3:使用json.Number类型

如果你希望保留浮点数的原始精度,但又想在JSON输出中保留小数点后两位零,可以使用json.Number类型。

package main

import (
    "encoding/json"
    "fmt"
    "strconv"
)

type Data struct {
    Value json.Number `json:"value"`
}

func main() {
    value := 123.456
    formattedValue := strconv.FormatFloat(value, 'f', 2, 64)

    data := Data{Value: json.Number(formattedValue)}
    jsonData, err := json.Marshal(data)
    if err != nil {
        fmt.Println("Error marshalling JSON:", err)
        return
    }

    fmt.Println(string(jsonData))
}

输出:

{"value":"123.46"}

方法4:使用fmt.Sprintf格式化浮点数

你也可以使用fmt.Sprintf来格式化浮点数,然后再将其序列化为JSON。

package main

import (
    "encoding/json"
    "fmt"
)

type Data struct {
    Value string `json:"value"`
}

func main() {
    value := 123.456
    formattedValue := fmt.Sprintf("%.2f", value)

    data := Data{Value: formattedValue}
    jsonData, err := json.Marshal(data)
    if err != nil {
        fmt.Println("Error marshalling JSON:", err)
        return
    }

    fmt.Println(string(jsonData))
}

输出:

{"value":"123.46"}

总结

以上方法都可以确保在JSON输出中保留小数点后两位零。选择哪种方法取决于你的具体需求和对代码的可维护性要求。如果你需要保留浮点数的原始精度,推荐使用json.Number类型或自定义JSON序列化方法。如果你只需要简单的格式化输出,使用strconv.FormatFloatfmt.Sprintf即可。