
Art generated by copilot
A Go library for handling monetary values and currency operations with type safety. It support formatting based on Locale provided by https://cldr.unicode.org/
Money calculations require strict type safety to prevent costly mistakes. Fulus enforces this at compile time using Go generics:
package main
import (
"fmt"
"github.com/khatibomar/fulus"
"github.com/khatibomar/fulus/currency"
"github.com/khatibomar/fulus/locale"
)
func main() {
usd := fulus.NewMoney[currency.USD](1000) // $10.00
eur := fulus.NewMoney[currency.EUR](500) // €5.00
// This will not compile. compiler will throw this error.
// cannot use eur (variable of struct type fulus.Money[currency.EUR])
// as fulus.Money[currency.USD] value in argument to usd.Add
// usd.Add(eur)
ratio := fulus.Ratio[currency.EUR, currency.USD]{
Numerator: 104565, // 1.04565 represented as 104565/100000
Denominator: 100000,
}
eurInUsd, _, err := fulus.Convert(eur, ratio)
if err != nil {
panic(err)
}
fmt.Println(eurInUsd) // $5.22
usd, err = usd.Add(eurInUsd)
if err != nil {
panic(err)
}
fmt.Println(usd) // $15.22
fmt.Println(usd.Format(locale.FR)) // 15,22 $US
}
This prevents common mistakes like:
- Accidentally mixing different currencies in calculations
- Using floating point numbers for money (uses int64 internally)
- Imprecise currency conversions
Don't see your currency in the list? No problem! You can easily create custom currency types that are specific to your financial domain's needs.
Let's introduce kanna currency.
package main
import (
"fmt"
"github.com/khatibomar/fulus"
"github.com/khatibomar/fulus/currency"
"github.com/khatibomar/fulus/locale"
)
var _ currency.Currency = KANNA{}
type KANNA struct{}
func (k KANNA) Code() string { return "KANNA" }
func (k KANNA) Name() string { return "Kanna Kamui" }
func (k KANNA) Number() string { return "001" }
func (k KANNA) MinorUnits() int { return 2 }
func (k KANNA) FormatInfo(loc locale.Locale) currency.CurrencyFormatInfo {
switch loc {
case locale.JA:
return currency.CurrencyFormatInfo{
Symbol: "🐲",
Format: "#,##0.00 ¤",
GroupSeparator: "⚔︎",
DecimalSeparator: "🦖",
MinusSign: "⛔",
}
default:
return currency.CurrencyFormatInfo{
Symbol: "🐉",
Format: "¤ #,##0.00",
GroupSeparator: ",",
DecimalSeparator: ".",
MinusSign: "-",
}
}
}
func main() {
kanna := fulus.NewMoney[KANNA](-1000000)
fmt.Println(kanna) // -🐉 10,000.00
kanna, _ = kanna.Mul(2)
fmt.Println(kanna) // -🐉 20,000.00
fmt.Println(kanna.Format(locale.JA)) // ⛔20⚔︎000🦖00 🐲
}
- Type-safe money operations using Go generics
- Prevention of invalid currency operations at compile time
- Safe decimal arithmetic using integer math
- Support for distribution and allocation of money
- JSON marshaling/unmarshaling support
This library was inspired by the blog post How to deal with Money in Software by Christian Sejersen.