A currency identifies the monetary unit of an amount and determines how many decimal places that amount can use. In a Go money converter, a Currency holds a three-letter code and a precision; an Amount pairs that Currency with a Decimal quantity. Keeping these fields private prevents callers from changing an amount’s currency after construction. section 6.1.1 section 6.2.5
Build and use a currency in three steps:
- Parse a code with ParseCurrency. It rejects codes whose length is not three; the example assigns listed currencies a precision of zero, one, or three decimal places and defaults the rest to two. This is not complete ISO-4217 validation. section 6.2.5
- Create an Amount with NewAmount. It rejects a Decimal that has more decimal places than its Currency permits, then sets the quantity’s precision to match the currency. section 6.2.6
- Convert an Amount using an exchange rate and a target Currency. The target supplies the output precision. The shown applyExchangeRate implementation divides away excess subunits rather than implementing a separate rounding step. section 6.3.1
A precision check
CAD uses two decimal places in this converter: 19.8875 CAD is rejected rather than silently treated as a valid transaction amount. At the command line, `change -from EUR -to USD 413.98` supplies the source currency, target currency, and amount separately. section 6.2.6 section 6.4.1
Listing 6.13 currency.go: Function for supported currencies
// ErrInvalidCurrencyCode is returned when the currency
// to parse is not a standard 3-letter code.
const ErrInvalidCurrencyCode =
Error("invalid currency code") #1
// ParseCurrency returns the currency associated to
// a name and may return ErrInvalidCurrencyCode.
func ParseCurrency(code string) (Currency, error) {
if len(code) != 3 { #2
return Currency{}, ErrInvalidCurrencyCode
}
switch code {
case "IRR":
return Currency{code: code, precision: 0}, nil
case "CNY", "VND": #3
return Currency{code: code, precision: 1}, nil
case "BHD", "IQD", "KWD", "LYD", "OMR", "TND": #3
return Currency{code: code, precision: 3}, nil
default:
return Currency{code: code, precision: 2}, nil #4
}
}
Inspect the Go parser’s precision cases and its two-decimal-place default; a three-character check alone does not verify that a code names a real currency. section 6.2.5
This converter is a learning project, not a transaction tool. It supports decimal currencies, restricts the input format, and hardcodes precision exceptions; real-world currency validation would need an updatable list. section 6.0 section 6.2.5

