GoLang library to make working with money safer, easier, and fun!
![]() |
- No dependencies - No anaemic model - JSON formatter - SQL driver - Localized formatter(s) |
---|---|
Money Value Object | "If I had a dime for every time I've seen someone use FLOAT to store currency, I'd have $999.997634"-- Bill Karwin In short: You shouldn't represent monetary values by a float. Wherever you need to represent money, use this Money value object. |
package main
import (
"fmt"
"github.com/radical-app/money"
)
func main() {
fiveEur := money.EUR(500) // see list of all currencies
tenEur, err := fiveEur.Add(fiveEur)
fmt.Print(err)
zeroEur, err := tenEur.Subtract(tenEur)
fmt.Print(err)
zeroEur.IsZero() // true
anotherFiveEur,err := zeroEur.Add(fiveEur)
fmt.Print(err)
fiveEur.IsEquals(anotherFiveEur) // true
fmt.Print(fiveEur.String()) // EUR 500 for beautiful formatter see below
}
Money from Int and only if you really-really-really need ...Forge from Float
usd312 := money.USD(312)
usd312, err := money.Forge(312, "USD")
usd312 := money.USD(312)
usd312, err := money.Forge(312, "USD")
usd312 := money.FloatUSD(3.12)
usd312, err := money.ForgeFloat(3.12, "USD")
.Parse() is the opposite of .String()
usd312, err := money.Parse("USD 312")
usd312.String() // "USD 312"
usd312, err := money.Parse("USD 312")
usd312.String() // "USD 312"
eur312, err := money.ParseWithFallback("312", "EUR")
// this uses EUR because the string has it
eur312, err := money.ParseWithFallback("EUR 312", "JPY")
// not suggested solution use ParseWithFallback if you have to deal with multiple currencies
money.DefaultCurrencyCode="JPY"
jpy312, err := money.Parse("312")
Custom Marshaller from and to Json
json.Marshal(money.EUR(123))
json.Marshal(money.EUR(123))
will produce the simplified json for money.DTO
:
{"amount":123,"currency":"EUR","symbol":"€","cents":100}
and
m := &Money{}
json.Unmarshal([]byte('{"amount":123,"currency":"EUR","symbol":"€","cents":100}'), m)
will produce the money.EUR(123)
money.EUR(123).String() // "EUR 123"
import "github.com/radical-app/money/moneyfmt"
import "github.com/radical-app/money"
moneyfmt.Display(money.EUR(123400), "ru") // € 1 234
moneyfmt.Display(money.EUR(123456), "ru") // € 1 234,56
moneyfmt.Display(money.EUR(123456), "it") // € 1.234,56
moneyfmt.Display(money.EUR(123400), "it") // € 1.234
moneyfmt.Display(money.EUR(123456), "en") // € 1,234.56
moneyfmt.Display(money.EUR(123456), "jp") // € 1,234.56
moneyfmt.Display(money.EUR(123456), "zh") // € 1,234.56
example at moneyfmt/moneyfmt_test.go
Is possible to use in mysql the field as int
or varchar
or if you really really need decimal(13,4)
_, err := db.Exec("insert into blablabla int, string, decimal (?,?,?)",
money.EUR(123).Int64(),
money.EUR(123).String(),
money.EUR(123).Float()
)
and the Scan during a select is auto-magically done:
rows.Scan(&moneyStoredAsInt64,
&moneyStoredAsString,
&moneyStoredAsFloat
)
Real example: driver_integration_test.go
The biggest amount you can store in is 92.233.720.368.547.758,07
the math.MaxInt64 / currency.cents