我当前的代码库定义了如下两种类型:
type Price uint64
type Quantity uint64
这样做效果很好,因为我不会意外地将Price
类型传递给Quantity
,否则编译器会抱怨。
现在我需要使用shopspring/decimal库将实现从uint64
切换到任意精度的decimal。
我想从以前的uint 64实现工作的以下要求:
- 如果我传递一个价格给一个期望数量的函数,反之亦然,编译器会抱怨
- 我可以在两个
Quantity
之间进行计算(比如调用Add
),而不需要任何额外的样板文件,但是对于在不同类型之间进行计算(比如将价格乘以数量),我需要通过执行一些操作(比如强制转换)来显式地允许它。 - 我不希望有重复的代码,比如定义我想为每个类型单独使用的每个方法(即使它委托给一个公共实现)
我尝试了3种不同的实现方式,但是没有一种能正常工作。有没有什么方法能满足我的需求?如果没有,推荐的方法是什么?
方法1
type Price decimal.Decimal
type Quantity decimal.Decimal
这个实现意味着我不能在decimal上使用方法。Decimal(比如Add()
)用于Price类型的变量,因为根据Go语言规范,“它不继承任何绑定到给定类型的方法”。
方法2
我可以像这样使用类型别名:
type Price = decimal.Decimal
type Quantity = decimal.Decimal
但是在这种情况下我可以将一个Price
传入一个期望Quantity
的函数中,这样我就不会得到类型保护。一些文档说类型别名主要是在重构过程中提供帮助。
方法3
我可以尝试使用嵌入式类型:
type Quantity struct {
decimal.Decimal
}
这在大多数情况下都有效,但在本例中:
qty.Add(qty2)
qty 2不是小数。小数所以我不得不做一些丑陋的事情
qty.Add(qty2.Decimal)
2条答案
按热度按时间xyhw6mcr1#
你可以在泛型中使用这种方法。对于你自己编写的类型来说,这样做更容易。如果你想用外部类型实现它,你将需要一个 Package 器。
示例:
现在,如果你想对
decimal.Decimal
这样的外部类型这样做,你不能编辑它的源代码来使它这样工作,你必须为任何你需要参数类型与接收者类型协变的方法编写 Package 器。例如,这里我假设您使用的是https://github.com/shopspring/decimal库:
对于每个具有协变类型的方法,您都需要一个 Package 器。
或者,您可以创建自己的库或派生现有库,然后使用第一个示例中的方法直接添加此特性:
例如,decimal. go的fork可能如下所示:
erhoui1w2#
哎呀,stephenbez已经试过我建议的了,删除!