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

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

JSON Value MyStruct formattedValue 159    来源:    2025-03-12

在Go语言中,处理浮点数精度丢失的问题时,尤其是在JSON输出中保留两位小数,可以通过以下几种方式来实现:

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

你可以先将 float64 类型的浮点数格式化为字符串,保留两位小数,然后再将其转换为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)

    myStruct := MyStruct{
        Value: formattedValue,
    }

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

    fmt.Println(string(jsonData))
}

输出:

{"value":"123.46"}

2. 使用 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)

    myStruct := MyStruct{
        Value: formattedValue,
    }

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

    fmt.Println(string(jsonData))
}

输出:

{"value":"123.46"}

3. 使用自定义 MarshalJSON 方法

如果你希望在结构体中直接控制 float64 的JSON输出格式,可以为结构体实现 MarshalJSON 方法。

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 []byte(fmt.Sprintf(`{"value":%s}`, formattedValue)), nil
}

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

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

    fmt.Println(string(jsonData))
}

输出:

{"value":123.46}

4. 使用 json.Number 类型

如果你希望保留原始数值的精度,并且只在输出时格式化,可以使用 json.Number 类型。

package main

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

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

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

    myStruct := MyStruct{
        Value: json.Number(formattedValue),
    }

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

    fmt.Println(string(jsonData))
}

输出:

{"value":"123.46"}

总结

以上几种方法都可以在Go语言中实现JSON输出时保留两位小数。选择哪种方法取决于你的具体需求和使用场景。如果你需要在整个项目中统一处理浮点数的精度问题,自定义 MarshalJSON 方法可能是一个不错的选择。如果只是偶尔需要格式化输出,使用 strconv.FormatFloatfmt.Sprintf 会更加灵活。