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

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

Value JSON formattedValue 点数 277    来源:    2025-03-14

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

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

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

package main

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

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

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

    data := MyStruct{
        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序列化

你可以通过实现json.Marshaler接口来自定义JSON序列化过程,以确保浮点数保留两位小数。

package main

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

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

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

func main() {
    data := MyStruct{
        Value: 123.456789,
    }

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

    fmt.Println(string(jsonData))
}

输出:

{"value":"123.46"}

方法3:使用math.Roundfmt.Sprintf

你可以使用math.Round函数将浮点数四舍五入到两位小数,然后使用fmt.Sprintf将其格式化为字符串。

package main

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

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

func main() {
    value := 123.456789
    roundedValue := math.Round(value*100) / 100
    formattedValue := fmt.Sprintf("%.2f", roundedValue)

    data := MyStruct{
        Value: formattedValue,
    }

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

    fmt.Println(string(jsonData))
}

输出:

{"value":"123.46"}

方法4:使用decimal

如果你需要更高精度的浮点数计算,可以使用第三方库如github.com/shopspring/decimal来处理浮点数。

package main

import (
    "encoding/json"
    "fmt"
    "github.com/shopspring/decimal"
)

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

func main() {
    value := decimal.NewFromFloat(123.456789)
    formattedValue := value.StringFixed(2)

    data := MyStruct{
        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输出中保留两位小数。选择哪种方法取决于你的具体需求和项目的复杂性。如果你只需要简单的格式化,方法1和方法3可能就足够了。如果你需要更复杂的处理或更高的精度,可以考虑使用方法2或方法4。