我在Go代码中使用shopspring/decimal而不是float64来防止数学错误。在编写我的protobuf文件以便通过gRPC传输这些值时,我可以使用:
double
转换为float64 string
这肯定会以自己的方式精确但是让我感到笨拙传统智慧教会我在货币应用中使用浮动物,但我可能过于小心,因为它是序列化的一个点。
答案 0 :(得分:0)
如果你真的需要任意精度,恐怕现在没有正确的答案。有 https://github.com/protocolbuffers/protobuf/issues/4406 打开,但似乎不是很活跃。如果没有内置支持,您将确实需要手动执行序列化,然后使用 string
或 bytes
来存储结果。在 string
和 bytes
之间使用哪一个可能取决于您是否需要跨平台/跨库兼容性:如果需要,请使用 string
并解析字符串中的十进制表示在阅读器中使用适当的任意精度类型;如果您不需要它并且您打算使用相同的 cpu 架构和库读取数据,您可能只需使用该库提供的二进制序列化 (MarshalBinary
/UnmarshalBinary
) 并使用bytes
。
另一方面,如果您只需要发送货币值而不需要任意精度,您可能只需使用 sint64
/uint64
并使用适当的单元。举个例子,如果您需要用 4 位十进制数字表示以美元为单位的货币价值,则您的单位将是一美元的 1/10000,例如值 1
表示 $0.0001,值 19900
表示 $1.99,-500000
表示 $-50,依此类推。使用这样的单位,您可以表示 $-922,337,203,685,477.5808 到 $922,337,203,685,477.5807 的范围 - 这对于大多数用途来说应该足够了。您仍然需要手动执行缩放,但它应该是相当简单和可移植的。鉴于上述范围,我建议使用 sint64
更好,因为它也允许您表示负值;仅当您需要额外的正范围而不需要负值时才应考虑 uint64
。
或者,如果您不介意导入另一个包,您可能想看看 https://github.com/googleapis/googleapis/blob/master/google/type/money.proto 或 https://github.com/googleapis/googleapis/blob/master/google/type/decimal.proto(顺便实现与上述两个模型非常相似的东西),以及https://pkg.go.dev/github.com/googleapis/go-type-adapters/adapters
处的相关效用函数作为旁注,您几乎不应该使用浮点数来表示货币值,这是完全正确的。