liveBook · Manning

Currency

As explained in Learn Go with Pocket-Sized Projects

A currency is a monetary system whose units and denomination rules determine how amounts are represented and valued.

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

How Learn Go with Pocket-Sized Projects covers it

How deep it goes
Defines a private-field Go value object, implements code parsing and precision cases, and checks amounts; stops short of complete currency-code validation.
Examples
Uses EUR and USD CLI flags, a rejected 19.8875 CAD amount, and parser tests for currencies with different precisions.
What it assumes
Assumes basic Go and CLI familiarity while building the Currency, Decimal, and Amount types incrementally.
What you can do after
Build it from scratch: parse currency codes, reject amounts with excessive precision, and use target precision when converting.
How it connects
Connects Currency to Amount, Decimal, exchange rates, fixed decimal precision, and CLI flags.

Also explained in

Compare how 2 books explain currency →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Go with Pocket-Sized Projects. The section links point to the parts of the book it draws on.