A currency exchange rate specifies how much target currency corresponds to one unit of source currency. A money-conversion CLI uses the rate to turn an input Amount into a new Amount in the requested currency; the input amount remains unchanged. section 6.0 section 6.3.1
Keep obtaining and applying the rate separate:
- Represent the rate with a dedicated ExchangeRate type. Multiply it by the amount’s decimal quantity, then adjust the result to the target currency’s precision. The illustrated implementation drops excess decimal places by division; it does not demonstrate conventional rounding. section 6.3.1
- Fetch the rate through a separate bank dependency rather than embedding an HTTP call in money conversion. This permits a hardcoded rate during development and replacement with a bank-backed implementation. section 6.3 section 6.5
- Report a failure when the response cannot be decoded or either currency’s rate is absent. section 6.5.4
Converting an ECB reference rate
The sample European Central Bank response lists USD at 1.0674 per EUR. At that sample rate, 10 EUR produces 10.674 USD before adjustment to USD’s two decimal places; the illustrated precision adjustment yields 10.67 USD. This is a worked software example, not a rate for a real transaction. section 6.5.4 section 6.3.1 section 6.0
ECB reference rates express each listed currency against one euro. Add EUR at a rate of 1, then calculate a source-to-target rate as targetFactor / sourceFactor. For example, converting CAD to ZAR uses the two EUR-based factors rather than requiring a separately published CAD-to-ZAR rate. section 6.5.4
Listing 6.45 envelope.go: Computing the exchange rate
// exchangeRate reads the change rate from the Envelope's contents.
func (e envelope) exchangeRate(
source, target string) (money.ExchangeRate, error) {
if source == target {
return 1., nil #1
}
rates := e.mappedChangeRates()
sourceFactor, sourceFound := rates[source] #2
if !sourceFound {
return 0, fmt.Errorf("failed to find the source currency %s",
source) #3
}
targetFactor, targetFound := rates[target] #4
if !targetFound {
return 0, fmt.Errorf("failed to find target currency %s", target)
}
return targetFactor / sourceFactor, nil #5
}
The rate-calculation listing shows the same-currency rate of 1, checks for missing currencies, and divides the target factor by the source factor. section 6.5.4
Test rate application with identity rates, very small or large rates, and target currencies with different precisions. The XML-decoding example reads rate attributes as float64, while the conversion design calls for decimal multiplication; the supplied fragments do not show a complete, consistent handoff between those representations. section 6.3.1 section 6.5.4
