跳到主要内容

Decimal

decimal 包重新导出 shopspring/decimal v1.4.0,用于任意精度 十进制算术,并额外提供 NewFromAny / MustFromAny 转换 helper。

Alias 契约

import "github.com/coldsmirk/vef-framework-go/decimal"

var price decimal.Decimal

decimal.Decimalshopspring/decimal.Decimal 的 type alias,不是 wrapper。 所有 Decimal.* methods 都是 upstream methods,签名和行为一致。该类型没有 exported fields。

VEF 重新导出了 constructors、constants 和 aggregators,但没有重新导出 upstream package-level knobs,例如 DivisionPrecisionMarshalJSONWithoutQuotesPowPrecisionNegativeExponentExpMaxIterations。如果应用必须修改这些全局设置,需要直接 import github.com/shopspring/decimal

Top-Level API

常量:

decimal.Zero // 0
decimal.One // 1

不要用 == 比较 decimal.Zero;使用 Decimal.EqualDecimal.Cmp

重新导出的 constructors:

decimal.New(value, exp) // raw value 和 exponent
decimal.NewFromInt(42) // int64
decimal.NewFromInt32(42) // int32
decimal.NewFromUint64(42) // uint64
decimal.NewFromFloat(3.14) // float64
decimal.NewFromFloat32(3.14) // float32
decimal.NewFromFloatWithExponent(3.14, -2) // 指定指数
decimal.NewFromBigInt(bigInt, exp) // *big.Int
decimal.NewFromBigRat(bigRat, precision) // *big.Rat
decimal.NewFromString("123.45") // string,返回 error
decimal.RequireFromString("123.45") // string,失败时 panic

decimal.NewFromFormattedString 的第二个参数是 *regexp.Regexp,用于在解析前 移除匹配到的格式字符:

cleanup := regexp.MustCompile("[$,]")
amount, err := decimal.NewFromFormattedString("$1,234.56", cleanup)

重新导出的 aggregators:

decimal.Max(a, b, c...)
decimal.Min(a, b, c...)
decimal.Sum(a, b, c...)
decimal.Avg(a, b, c...)
decimal.RescalePair(a, b)

VEF-specific helpers:

d, err := decimal.NewFromAny(value)
d = decimal.MustFromAny(value)

完整 top-level checklist:

GroupAPIs
Alias and constantsdecimal.Decimaldecimal.Zerodecimal.One
Constructorsdecimal.Newdecimal.NewFromIntdecimal.NewFromInt32decimal.NewFromUint64decimal.NewFromFloatdecimal.NewFromFloat32decimal.NewFromFloatWithExponentdecimal.NewFromBigIntdecimal.NewFromBigRatdecimal.NewFromStringdecimal.NewFromFormattedStringdecimal.RequireFromString
Conversion helpersdecimal.NewFromAnydecimal.MustFromAny
Aggregatorsdecimal.Maxdecimal.Mindecimal.Sumdecimal.Avgdecimal.RescalePair

NewFromAny

decimal.NewFromAny 会把常见 Go 值转换成 decimal.Decimal

支持的输入 family:

类型行为
Decimal*Decimal直接透传;nil *Decimal 返回 decimal.Zero
intint8int64整数转换
uintuint8uint64无符号整数转换
float32float64浮点数转换
string[]byte通过 NewFromString 解析
booltrue 转成 decimal.Onefalse 转成 decimal.Zero
fmt.Stringer解析其 String() 返回值

不支持的输入会返回 message 以 decimal: unsupported type 开头的 error;这个 sentinel 没有导出。decimal.MustFromAny 会在任何转换错误上 panic。

Method Families

因为 decimal.Decimal 是 type alias,method set 继承自 shopspring/decimal.Decimal。下表按用途对全部 70 个 exported methods 进行了分组。

FamilyMethods
ArithmeticDecimal.AbsDecimal.NegDecimal.AddDecimal.SubDecimal.MulDecimal.DivDecimal.DivRoundDecimal.ModDecimal.QuoRem
Powers and transcendental functionsDecimal.PowDecimal.PowBigIntDecimal.PowInt32Decimal.PowWithPrecisionDecimal.SinDecimal.CosDecimal.TanDecimal.AtanDecimal.LnDecimal.ExpTaylorDecimal.ExpHullAbrham
Comparison and signDecimal.CmpDecimal.CompareDecimal.EqualDecimal.EqualsDecimal.GreaterThanDecimal.GreaterThanOrEqualDecimal.LessThanDecimal.LessThanOrEqualDecimal.Sign
Rounding and scaleDecimal.CeilDecimal.FloorDecimal.RoundDecimal.RoundBankDecimal.RoundCashDecimal.RoundCeilDecimal.RoundDownDecimal.RoundFloorDecimal.RoundUpDecimal.ShiftDecimal.Truncate
Inspection and conversionDecimal.BigFloatDecimal.BigIntDecimal.RatDecimal.Float64Decimal.InexactFloat64Decimal.IntPartDecimal.CoefficientDecimal.CoefficientInt64Decimal.ExponentDecimal.NumDigitsDecimal.IsIntegerDecimal.IsNegativeDecimal.IsPositiveDecimal.IsZeroDecimal.Copy
String formattingDecimal.StringDecimal.StringFixedDecimal.StringFixedBankDecimal.StringFixedCashDecimal.StringScaled
Encoding, database, and scanner interfacesDecimal.MarshalBinaryDecimal.UnmarshalBinaryDecimal.MarshalJSONDecimal.UnmarshalJSONDecimal.MarshalTextDecimal.UnmarshalTextDecimal.GobEncodeDecimal.GobDecodeDecimal.ScanDecimal.Value

运行时注意点

  • Decimal.Div 在 quotient 不能整除时使用 upstream DivisionPrecision。 upstream 默认保留小数点后 16 位。
  • Decimal.DivDecimal.DivRoundDecimal.ModDecimal.QuoRem 遇到 division by zero 会 panic。
  • Decimal.MarshalJSON 默认输出 quoted JSON string,例如 "123.45"。 upstream MarshalJSONWithoutQuotes global 可以切换为 JSON number,但在 JavaScript 客户端中可能丢失精度。
  • Decimal.UnmarshalJSON 同时接受 quoted 和 numeric JSON input。
  • decimal.NewFromFloatdecimal.NewFromFloat32 会从 binary floating-point value 转换;金额类输入优先使用 decimal.NewFromString、整数 constructor 或 scaled integer storage。
  • Decimal.Float64 返回 (value, exact)Decimal.InexactFloat64 只返回最近 的 float64
  • decimal.NewFromFloatdecimal.NewFromFloat32decimal.NewFromFloatWithExponent 遇到 NaN 或 infinity 会 panic。

在模型中使用

type Product struct {
orm.FullAuditedModel
Name string `json:"name" bun:"name"`
Price decimal.Decimal `json:"price" bun:"price,type:decimal(10,2)"`
}

decimal.Decimal 类型完全支持:

  • Bun ORM(数据库扫描/取值)
  • JSON 序列化/反序列化
  • copier 包(值 ↔ 指针转换)
  • mapx 包(解码钩子)