# Money

GoMoney provides ability to work with monetary value using a currency's smallest unit. This package provides basic and precise Money operations such as rounding, splitting and allocating. Monetary values should not be stored as floats due to small rounding differences.

```package main

import "github.com/Rhymond/go-money"

func main() {
pound := money.New(100, "GBP")

if err != nil {
log.Fatal(err)
}

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
}```

## Quick start

Get the package:

`\$ go get github.com/Rhymond/go-money`

## Features

• Provides a Money struct which stores information about an Money amount value and its currency.
• Provides a `Money.Amount` struct which encapsulates all information about a monetary unit.
• Represents monetary values as integers, in cents. This avoids floating point rounding errors.
• Represents currency as `Money.Currency` instances providing a high level of flexibility.

## Usage

### Initialization

Initialize Money by using smallest unit value (e.g 100 represents 1 pound). Use ISO 4217 Currency Code to set money Currency

`pound := money.New(100, "GBP")`

## Comparison

Go-money provides base compare operations like:

• Equals
• GreaterThan
• GreaterThanOrEqual
• LessThan
• LessThanOrEqual

Comparisons must be made between the same currency units.

```pound := money.New(100, "GBP")
twoPounds := money.New(200, "GBP")
twoEuros := money.New(200, "EUR")

pound.GreaterThan(twoPounds) // false, nil
pound.LessThan(twoPounds) // true, nil
twoPounds.Equals(twoEuros) // false, error: Currencies don't match```

## Asserts

• IsZero
• IsNegative
• IsPositive

#### Zero value

To assert if Money value is equal to zero use `IsZero()`

```pound := money.New(100, "GBP")
result := pound.IsZero(pound) // false```

#### Positive value

To assert if Money value is more than zero use `IsPositive()`

```pound := money.New(100, "GBP")
pound.IsPositive(pound) // true```

#### Negative value

To assert if Money value is less than zero use `IsNegative()`

```pound := money.New(100, "GBP")
pound.IsNegative(pound) // false```

## Operations

• Subtract
• Multiply
• Absolute
• Negative

Comparisons must be made between the same currency units.

Additions can be performed using `Add()`.

```pound := money.New(100, "GBP")
twoPounds := money.New(200, "GBP")

result, err := pound.Add(twoPounds) // £3.00, nil```

#### Subtraction

Subtraction can be performed using `Subtract()`.

```pound := money.New(100, "GBP")
twoPounds := money.New(200, "GBP")

result, err := pound.Subtract(twoPounds) // -£1.00, nil```

#### Multiplication

Multiplication can be performed using `Multiply()`.

```pound := money.New(100, "GBP")

result := pound.Multiply(2) // £2.00```

#### Absolute

Return `absolute` value of Money structure

```pound := money.New(-100, "GBP")

result := pound.Absolute() // £1.00```

#### Negative

Return `negative` value of Money structure

```pound := money.New(100, "GBP")

result := pound.Negative() // -£1.00```

## Allocation

• Split
• Allocate

#### Splitting

In order to split Money for parties without losing any pennies due to rounding differences, use `Split()`.

After division leftover pennies will be distributed round-robin amongst the parties. This means that parties listed first will likely receive more pennies than ones that are listed later.

```pound := money.New(100, "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```

#### Allocation

To perform allocation operation use `Allocate()`.

It splits money using the given ratios without losing pennies and as Split operations distributes leftover pennies amongst the parties with round-robin principle.

```pound := money.New(100, "GBP")
// slice (int[]{33, 33, 33}...) or separated by a comma integers
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```

## Format

To format and return Money as a string use `Display()`.

`money.New(123456789, "EUR").Display() // €1,234,567.89`

To format and return Money as a float64 representing the amount value in the currency's subunit use `AsMajorUnits()`.

`money.New(123456789, "EUR").AsMajorUnits() // 1234567.89`

## Contributing

Thank you for considering contributing! Please use GitHub issues and Pull Requests for contributing.

• #### Multiply and Divide only accept an int

`Multiply` and `Divide` only accept an int. What was the reason for this? It seems to lessen the usefulness of these functions. For example, calculating the net value from gross is impossible.

``````gross := money.New(599, "GBP")
net := gross.Divide(1.2) // error
tax, _ := gross.Subtract(net)
``````

or am I missing something and this is possible in another way?

@Rhymond I've waited to be merged #38, but it looks have not updated long time. I need JSON marshaling/unmarshaling feature for go-money. I've tried to update and fix it. Could you check this PR?

opened by k315k1010 11
• #### Refactor for abstraction

• Amount struct with conversion methods and hidden internals
• Remove all pointers and dereferences. Unneeded. This should be faster (stay on stack)
• Remove calculator file and move all calculations to new Amount object

Due to the Amount struct hiding the internals, we can change the implementation to a `Big` implementation in the future, if necessary, without impacting existing code. We would simply add a `Big()` method to return the internal as a `Big`, as well as alter how the `toAmount` function parses the incoming values.

opened by tylerstillwater 11
• #### Proposal: Add function NewFromFloat

It would be really useful to be able to create a new Money struct from a float or maybe a decimal string ('1.243'). Formatting the decimal amount from a source (API response, file, ...) to a Money struct can get really tedious, that's why I propose a util function inside the money package for dealing with this cases.

This is my current implementation:

``````func NewFromFloat(amount float64, currency string) *money.Money {
currencyDecimals := math.Pow(10, float64(money.GetCurrency(currency).Fraction))
amountCents := int64(amount * currencyDecimals)
return money.New(amountCents, currency)
}
``````

To not lose precision dealing with floats there can also be a NewFromString, but I haven gotten around to implementing it.

What do you guys think?

opened by npinochet 6
• #### Question about the rounding for NewFromFloat

Love the new addition of `NewFromFloat`. Just wanted to get a clearer understanding of always rounding trailing decimals down when given.

`````` cents := money.NewFromFloat(99.999999, money.USD)
//->  cents: 9999
``````

Just want to know the why between getting 9999 vs 10000?

Thanks!

opened by TimothyIp 5
• #### Find Currency by numeric code

Hello, I'm adding the option to search Currencies by its numeric code ISO number. This helps because many implementations works around the iso numerical code numbers (like Visa and Mastercard for instance).

• This code will load a second map of currencies but now this map uses the numerical ISO code as key of the map.
• The reason to have another map is to avoid having a loop each time we need to access a currency its iso numerical code
• Added idea and ds_store files to git ignore
opened by Stocco 5
• #### Addition of currency code constants

See #72 for the original proposal.

This pull request includes the addition of constants for the 168 ISO 4217 currency codes that are currently present in this package.

In addition to adding these, I have updated the map of currencies in `currency.go` for both the key in the map and the currency code in the struct to be returned. Similarly, I have updated the tests to include their usage and updated the examples in the README to include their usage.

Definitely willing to have a discussion about how we include their usage in the README. This is certainly the part of this pull request that I have the most questions about so far. In particular, I worry about causing confusion with the usage of the constants with regards to a consumer of the package adding their own currencies.

opened by jamesallured 5
• #### Use of int causes overflows and arch-specific variability

Using the architecture-independent `int` type will cause 32-bit binaries to overflow if more than `21,474,836.47` is used in a base-100 currency, introducing architecture-dependent behaviour differences which may not be caught.

This can be resolved by switching amounts to use the `int64` data type. This will still work on 32-bit architectures, at the slight expense of performance, and allow base-100 currency values up to an amount of `92,233,720,368,547,758.07` ... More than likely enough for most consumers of this package :)

opened by bbrks 5
• #### Get Currency by Numeric Code

Code changes allow to get the currency by numeric code or a code used to index currencies map. The PR fixes issues with the PR https://github.com/Rhymond/go-money/pull/96

opened by Rhymond 4
• #### go get fails

Running `go get github.com/rhymond/go-money` fails and spits out the message:

``````go: github.com/rhymond/[email protected]: parsing go.mod: unexpected module path "github.com/Rhymond/go-money"
``````

seems to be related to https://github.com/golang/go/issues/27154

opened by logitick 4
• #### Does not have i18n for formatting ?

Am building a templating system and need to handle currency properly. Does this library have functionality for this ? E.g in Sweden and Germany money is displayed differently

If you know of I lib I can combine and PR if you want too

opened by ghost 4
• #### Digit separation in INR amount

Hi,

When using INR currency format, we are not getting the desired result:

Result:

1000.00 -> ₹1,000.00 (As expected) 10000.00 -> ₹10,000.00 (As expected) 100000.00 -> ₹100,000.00 (Expected ₹1,00,000.00) 1000000.00 -> ₹1,000,000.00 (Expected ₹10,00,000.00)

and so on

Can you provide a solution for this since this is regarding the placement of separator not the value of separator?

opened by amitesh-furlenco 0
• #### fixed NewFromFloat to calculate accurate values

Multiplying floats by primitive types is not precise enough, and there is a serious bug that the amount generated by NewFromFloat is different from the original value. issue : https://github.com/Rhymond/go-money/issues/121, #124

Fixed to use "github.com/shopspring/decimal" for float multiplication.

This fix requires a dependency on an external module,, but I could find no other idea.

opened by kotaroyamazaki 1
• #### Fixed GetCurrency to be case-insensitive

~~NewFromFloat did not support lowercase currency codes because it used getCurrencyByCode. As same as New(), fix to use newCurrency(code).get() instead.~~

Fixed GetCurrency to be case-insensitive so that it wouldn't fail at upper case.

opened by kotaroyamazaki 0
• #### NewFromFloat trouble

Why is the float64 value equal to 1.15 created in the money type as 1.14? The link below shows an example of the supposed error: https://go.dev/play/p/Z64XrP8LdTc

opened by font1k 3

## What's Changed

• Fix Any reason for Amount being a data-structure? #73 by @totemcaf in https://github.com/Rhymond/go-money/pull/113
• Add NewFromFloat (#108) by @npinochet in https://github.com/Rhymond/go-money/pull/116

## New Contributors

• @totemcaf made their first contribution in https://github.com/Rhymond/go-money/pull/113
• @npinochet made their first contribution in https://github.com/Rhymond/go-money/pull/116

Full Changelog: https://github.com/Rhymond/go-money/compare/v1.0.8...v1.0.9

Source code(tar.gz)
Source code(zip)

## What's Changed

• Fix ARS decimal and thousand separators and add testable examples by @unkiwii in https://github.com/Rhymond/go-money/pull/81

## New Contributors

• @unkiwii made their first contribution in https://github.com/Rhymond/go-money/pull/81

Full Changelog: https://github.com/Rhymond/go-money/compare/v1.0.7...v1.0.8

Source code(tar.gz)
Source code(zip)

## What's Changed

• Add XOF and MGA currencies by @r1cm3d in https://github.com/Rhymond/go-money/pull/110

## New Contributors

• @r1cm3d made their first contribution in https://github.com/Rhymond/go-money/pull/110

Full Changelog: https://github.com/Rhymond/go-money/compare/v1.0.6...v1.0.7

Source code(tar.gz)
Source code(zip)

## What's Changed

• Split small negative values fix @arzonus in https://github.com/Rhymond/go-money/pull/107

Full Changelog: https://github.com/Rhymond/go-money/compare/v1.0.5...v1.0.6

Source code(tar.gz)
Source code(zip)

## What's Changed

• Get Currency by Numeric Code by @Stocco in https://github.com/Rhymond/go-money/pull/104

Full Changelog: https://github.com/Rhymond/go-money/compare/v1.0.4...v1.0.5

Source code(tar.gz)
Source code(zip)
• #### v1.0.4(Mar 31, 2022)

• Ubuntu version changed from `ubuntu-16.04` to `latest` in github workflow
• Merged #101 Fix marshalling the zero value of Money to JSON. Thanks @bencrouse
• Merged #94 Fix negative split remainder. Thanks @ConradKurth
Source code(tar.gz)
Source code(zip)

• #### v0.4.0(Jul 26, 2019)

• Updated list of currencies.
• Added AsMajorUnits function to return Money as a float64 representing the amount value in the currency's subunit.
Source code(tar.gz)
Source code(zip)

• #### v0.0.1(Apr 3, 2017)

###### Raymond
In order to understand recursion, you must first understand recursion
###### Go library containing a collection of financial functions for time value of money (annuities), cash flow, interest rate conversions, bonds and depreciation calculations.

go-finance Go library containing a collection of financial functions for time value of money (annuities), cash flow, interest rate conversions, bonds

143 Jan 2, 2023
###### Mobile Money API Handyman

pesakit pesakit is a highly configurable commandline tool that comes in handy during testing and development of systems that integrate with mobile mon

2 Nov 22, 2021
###### fastme - Fast extensible matching engine Go implementation.

fastme (fast golang matching engine) library Design The library solves the task of recalculating the exchange order book. A classic matching engine co

37 Sep 26, 2022
###### Go-ant-pattern: An ant pattern parser

go-ant-pattern - An ant pattern parser. Usage package main import ( "fmt" "github.com/cbuschka/go-ant-pattern" ) func main() { path := "

0 Dec 7, 2021

0 Jan 24, 2022
###### money and currency formatting for golang

accounting - money and currency formatting for golang accounting is a library for money and currency formatting. (inspired by accounting.js) Quick Sta

782 Dec 21, 2022
###### Go library containing a collection of financial functions for time value of money (annuities), cash flow, interest rate conversions, bonds and depreciation calculations.

go-finance Go library containing a collection of financial functions for time value of money (annuities), cash flow, interest rate conversions, bonds

143 Jan 2, 2023
###### Mobile Money API Handyman

pesakit pesakit is a highly configurable commandline tool that comes in handy during testing and development of systems that integrate with mobile mon

2 Nov 22, 2021
###### Building block for mobile money api clients

base the base code for creating mobile money api clients using golang build request request := NewRequestBuilder("login request", http.MethodPost, "ht

3 Jan 4, 2022
###### MTN Mobile Money API Client in Go

mtnmomo-go This package provides a generic go client template for the MTN Mobile Money API Installation mtnmomo-go is compatible with modern Go releas

4 Dec 27, 2022
###### Money Cheat - Need For Speed Underground 2

nfsu2-money-cheat Money cheat for "Need For Speed Underground 2" -- allows you to edit/change money within your NFSU2 save file. Download EXE Link: ht

5 Nov 3, 2022
###### Suricate-bank - API to transfer money between accounts at Suricate Bank,written in Go

⚠️ WORK IN PROGRESS ⚠️ Suricate Bank is an api that creates accounts and transfe

12 Oct 8, 2022

Temporal Go Project Template This is a simple project for demonstrating Temporal with the Go SDK. The full 20 minute guide is here: https://docs.tempo

0 Jan 6, 2022
###### Money-transfer-project-template-go - A simple project for demonstrating Temporal with the Go SDK

Temporal Go Project Template This is a simple project for demonstrating Temporal

0 Feb 5, 2022
###### Side-scroller indie game written in go - "it costs money to be alive"

it costs money to be alive A short, non-fighty indie side scroller game. Run with the right / left arrow keys, jump with up arrow or space. Collect co

6 Nov 23, 2022
###### 🚦 Semaphore pattern implementation with timeout of lock/unlock operations.

?? semaphore Semaphore pattern implementation with timeout of lock/unlock operations. ?? Idea The semaphore provides API to control access to a shared

93 Dec 7, 2022
###### The implementation of the pattern observer

Event This is package implements pattern-observer Fast example import ( "github.com/agoalofalife/event" ) func main() { // create struct e := even

50 Dec 4, 2022
###### An efficient and feature complete Hystrix like Go implementation of the circuit breaker pattern.

Circuit Circuit is an efficient and feature complete Hystrix like Go implementation of the circuit breaker pattern. Learn more about the problems Hyst

681 Dec 28, 2022
###### A go library that facilitates the implementation of decorator pattern.

go-decorator go-decorator is a library that facilitates the implementation of decorator pattern. Installation To install go-decorator, use go get: go

1 Nov 25, 2021
###### Go language implementation of a blockchain based on the BDLS BFT protocol. The implementation was adapted from Ethereum and Sperax implementation

BDLS protocol based PoS Blockchain Most functionalities of this client is similar to the Ethereum golang implementation. If you do not find your quest

1 Oct 14, 2022