如何为高精度小数定义两类专属类型,实现类型隔离与便捷计算?
问题描述
原有代码通过自定义类型实现类型安全:
type Price uint64 type Quantity uint64
该实现能避免将Price误传入期望Quantity的函数,编译器会直接报错。
现在需要将底层类型从uint64切换为shopspring/decimal的高精度小数,同时保留以下特性:
- 类型安全:
Price与Quantity互传时编译器报错 - 同类型便捷计算:两个
Quantity可直接调用Add等方法,无需额外代码;不同类型(如Price乘Quantity)需显式转换后才能计算 - 避免重复代码:无需为每个类型重复定义方法(即使是委托给公共实现)
尝试过三种方案均无法满足需求:
方案1:自定义新类型
type Price decimal.Decimal type Quantity decimal.Decimal
问题:新类型无法继承原类型的方法(如Add()),不符合Go语言规范,无法直接调用decimal库的计算方法。
方案2:类型别名
type Price = decimal.Decimal type Quantity = decimal.Decimal
问题:失去类型保护能力,Price和Quantity可互相传入对方的函数,不符合类型安全要求。
方案3:嵌入类型
type Quantity struct { decimal.Decimal }
问题:调用qty.Add(qty2)时,因参数类型不匹配,必须写qty.Add(qty2.Decimal)这类冗余代码,不符合便捷计算的需求。
请问是否有其他可行方案?若无,推荐哪种实现方式?
可行方案推荐
核心思路:嵌入类型+同类型方法适配
基于方案3的嵌入类型,为每个自定义类型(Price/Quantity)实现适配同类型参数的计算方法,内部委托给decimal.Decimal的原生方法。这样既保留类型安全,又能实现同类型直接调用方法,同时通过代码生成避免重复编写代码。
示例实现
- 定义基础嵌入结构:
import "github.com/shopspring/decimal" type Price struct { decimal.Decimal } type Quantity struct { decimal.Decimal }
- 为每个类型实现同类型参数的计算方法(以
Add为例):
// Price的Add方法,仅接收Price类型参数 func (p Price) Add(other Price) Price { return Price{p.Decimal.Add(other.Decimal)} } // Quantity的Add方法,仅接收Quantity类型参数 func (q Quantity) Add(other Quantity) Quantity { return Quantity{q.Decimal.Add(other.Decimal)} }
同理可实现Sub、Mul、Div等其他需要的方法,每个方法都是简单的委托逻辑,代码量极小。
- 用代码生成简化重复工作
如果需要实现的方法较多,可通过go generate结合text/template模板工具自动生成这些适配方法。例如编写一个模板文件,指定需要生成的方法列表,然后通过脚本为Price和Quantity批量生成方法,彻底避免重复代码。
特性满足情况
- 类型安全:
Price和Quantity是不同的结构体类型,互传时编译器会报错 - 同类型便捷计算:调用
price1.Add(price2)或qty1.Add(qty2)即可完成计算,无需额外转换 - 避免重复代码:方法逻辑都是简单委托,且可通过代码生成批量创建,无需手动重复编写每个类型的所有方法
不同类型计算的处理
当需要跨类型计算(如Price乘Quantity),需显式提取内部的decimal.Decimal值进行计算,例如:
// 计算总价:Price * Quantity totalDecimal := price.Decimal.Mul(qty.Decimal) // 如需转换为自定义类型(比如定义Total类型),可手动包装 total := Total{totalDecimal}
这种显式转换刚好符合“不同类型需显式转换后计算”的需求。
内容的提问来源于stack exchange,提问作者stephenbez
相关产品推荐
相关产品推荐

