golang实现Fowler货币模式的高效处理插件库go-money的使用
Golang实现Fowler货币模式的高效处理插件库go-money的使用
简介
GoMoney提供了使用货币最小单位处理货币值的能力。这个包提供了基本且精确的货币操作,如四舍五入、拆分和分配。由于小的舍入差异,货币值不应存储为浮点数。
快速开始
安装包:
$ go get github.com/Rhymond/go-money
特性
- 提供Money结构体,存储货币金额值及其货币信息
- 提供
Money.Amount
结构体,封装所有关于货币单位的信息 - 以整数形式表示货币值,以分为单位,避免浮点舍入错误
- 以
Money.Currency
实例表示货币,提供高度灵活性
使用示例
初始化
使用最小单位值初始化Money(例如100表示1英镑)。使用ISO 4217货币代码设置货币。注意,所有ISO 4217货币代码也提供了常量。
pound := money.New(100, money.GBP)
或者使用直接金额初始化Money:
quarterEuro := money.NewFromFloat(0.25, money.EUR)
完整示例
package main
import (
"log"
"github.com/Rhymond/go-money"
)
func main() {
// 初始化1英镑
pound := money.New(100, money.GBP)
// 加法操作
twoPounds, err := pound.Add(pound)
if err != nil {
log.Fatal(err)
}
// 将2英镑分成3份
parties, err := twoPounds.Split(3)
if err != nil {
log.Fatal(err)
}
// 显示分配结果
parties[0].Display() // £0.67
parties[1].Display() // £0.67
parties[2].Display() // £0.66
}
比较操作
Go-money提供基本的比较操作:
- Equals
- GreaterThan
- GreaterThanOrEqual
- LessThan
- LessThanOrEqual
- Compare
比较必须在相同货币单位之间进行。
pound := money.New(100, money.GBP)
twoPounds := money.New(200, money.GBP)
twoEuros := money.New(200, money.EUR)
pound.GreaterThan(twoPounds) // false, nil
pound.LessThan(twoPounds) // true, nil
twoPounds.Equals(twoEuros) // false, error: Currencies don't match
twoPounds.Compare(pound) // 1, nil
pound.Compare(twoPounds) // -1, nil
pound.Compare(pound) // 0, nil
pound.Compare(twoEuros) // pound.amount, ErrCurrencyMismatch
断言
- IsZero
- IsNegative
- IsPositive
零值
pound := money.New(100, money.GBP)
result := pound.IsZero() // false
正值
pound := money.New(100, money.GBP)
pound.IsPositive() // true
负值
pound := money.New(100, money.GBP)
pound.IsNegative() // false
运算操作
- Add
- Subtract
- Multiply
- Absolute
- Negative
加法
pound := money.New(100, money.GBP)
twoPounds := money.New(200, money.GBP)
result, err := pound.Add(twoPounds) // £3.00, nil
减法
pound := money.New(100, money.GBP)
twoPounds := money.New(200, money.GBP)
result, err := pound.Subtract(twoPounds) // -£1.00, nil
乘法
pound := money.New(100, money.GBP)
result := pound.Multiply(2) // £2.00
绝对值
pound := money.New(-100, money.GBP)
result := pound.Absolute() // £1.00
负值
pound := money.New(100, money.GBP)
result := pound.Negative() // -£1.00
分配
拆分
pound := money.New(100, money.GBP)
parties, err := pound.Split(3)
if err != nil {
log.Fatal(err)
}
parties[0].Display() // £0.34
parties[1].Display() // £0.33
parties[2].Display() // £0.33
分配
pound := money.New(100, money.GBP)
// Allocate是可变参数函数,可以接收切片或逗号分隔的整数
parties, err := pound.Allocate(33, 33, 33)
if err != nil {
log.Fatal(err)
}
parties[0].Display() // £0.34
parties[1].Display() // £0.33
parties[2].Display() // £0.33
格式化
显示
money.New(123456789, money.EUR).Display() // €1,234,567.89
作为主单位
money.New(123456789, money.EUR).AsMajorUnits() // 1234567.89
贡献
感谢您的贡献!请使用GitHub问题和拉取请求进行贡献。
许可证
MIT许可证。有关更多信息,请参阅许可证文件。
更多关于golang实现Fowler货币模式的高效处理插件库go-money的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang实现Fowler货币模式的高效处理插件库go-money的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Go-Money: Golang中的Fowler货币模式实现
go-money是一个遵循Martin Fowler提出的货币模式的Golang库,它提供了安全、精确的货币计算功能,避免了浮点数运算带来的精度问题。
核心特性
- 精确的货币计算,使用整数存储货币值
- 支持多种货币和汇率转换
- 线程安全
- 符合Fowler货币模式
安装
go get github.com/Rhymond/go-money
基本使用示例
创建货币金额
package main
import (
"fmt"
"github.com/Rhymond/go-money"
)
func main() {
// 创建100美元
dollars := money.New(10000, "USD") // 100.00美元,内部存储为10000美分
// 创建5000日元
yens := money.New(5000, "JPY") // 5000日元,没有小数位
fmt.Println(dollars.Display()) // 输出: $100.00
fmt.Println(yens.Display()) // 输出: ¥5,000
}
算术运算
// 加法
sum := dollars.Add(money.New(5000, "USD")) // 100 + 50 = 150美元
// 减法
diff := dollars.Subtract(money.New(2000, "USD")) // 100 - 20 = 80美元
// 乘法
product := dollars.Multiply(3) // 100 * 3 = 300美元
// 除法
quotient, err := dollars.Divide(4) // 100 / 4 = 25美元
if err != nil {
fmt.Println("除法错误:", err)
}
fmt.Println(sum.Display(), diff.Display(), product.Display(), quotient.Display())
比较操作
// 相等比较
isEqual := dollars.Equals(money.New(10000, "USD")) // true
// 大于比较
isGreater := dollars.GreaterThan(money.New(5000, "USD")) // true
// 小于比较
isLess := dollars.LessThan(money.New(15000, "USD")) // true
fmt.Println(isEqual, isGreater, isLess)
高级功能
货币格式化
// 获取格式化后的字符串
fmt.Println(dollars.Display()) // $100.00
// 获取货币符号
fmt.Println(dollars.Currency().Code) // USD
fmt.Println(dollars.Currency().Symbol) // $
分配金额
// 将100美元分配给3个人
shares, remainder := dollars.Allocate(3)
for i, share := range shares {
fmt.Printf("Person %d gets %s\n", i+1, share.Display())
}
fmt.Printf("Remainder: %s\n", remainder.Display())
汇率转换
// 假设汇率为1 USD = 110 JPY
converted, err := dollars.Convert("JPY", 110)
if err != nil {
fmt.Println("转换错误:", err)
return
}
fmt.Printf("%s = %s\n", dollars.Display(), converted.Display())
最佳实践
- 始终使用最小货币单位存储:如美元使用美分,日元使用元
- 避免混合货币运算:不同货币间的运算应该先进行转换
- 处理分配余数:分配操作会产生余数,需要适当处理
- 错误处理:除法、转换等操作可能出错,需要检查错误
- 使用常量定义货币代码:避免硬编码货币代码
性能考虑
go-money使用int64存储金额,运算速度快且无精度损失。相比使用float64的方案:
- 避免了浮点数精度问题(如0.1 + 0.2 ≠ 0.3)
- 计算速度更快(整数运算通常比浮点运算快)
- 内存占用更小(int64比处理高精度浮点数更高效)
总结
go-money库为Golang提供了符合Fowler货币模式的实现,是处理金融计算的理想选择。它解决了浮点数精度问题,提供了丰富的货币操作API,并且易于集成到现有项目中。
对于需要处理货币的Golang应用,特别是金融、电商等领域,go-money是一个值得考虑的解决方案。