技术问询:如何为golang.org/x/text/currency添加新货币支持
Alright, let's walk through exactly how to add a new currency to the golang.org/x/text/currency package. I've tinkered with this package's internals before, so here's a practical, step-by-step breakdown:
First, you need all standard details for the new currency from the ISO 4217 standard:
- Three-letter alphabetic code (e.g., "XYZ")
- Numeric code (e.g., 123)
- Default number of decimal places (most use 2, some like JPY use 0)
- Official name (e.g., "XYZ Dollar")
- Localized names for major locales (if you want full i18n support)
The package stores core currency data in the internal/currency subdirectory. You'll need to modify key files here:
cldr.go: This file maps CLDR (Unicode Common Locale Data Repository) data to internal structures. Add your new currency's entries to relevant maps (likecurrencyNamesfor localized names,numericCodesfor ISO numeric code mappings).currency.go: Look for internal unit definitions or index mappings. Add your currency's details to the appropriate slices/structs that powercurrency.Unitlookups.- Check for generated files: If there's a
gen.gotool ininternal/currency, it likely generatestables.gofrom CLDR sources. If your currency is in the latest CLDR data, running this generator might auto-populate entries—otherwise, manually add lookup entries totables.go.
currency.Unit Constant In the top-level currency package (usually currency.go), add a new public Unit variable/constant pointing to your currency's internal index:
// XYZ represents the XYZ Dollar currency (ISO 4217 code XYZ). var XYZ = Unit{index: xyzIndex}
If the package uses const declarations for existing currencies, follow that pattern:
const ( // ... existing currency constants XYZ = Unit{index: xyzIndex} )
Ensure xyzIndex matches the index you assigned in internal data structures.
Many x/text packages rely on generated code to sync with CLDR data. If there's a gen.go in internal/currency, run it to update auto-generated tables:
cd internal/currency go run gen.go
This ensures your new currency's data is properly indexed and integrated into lookup logic.
Write a quick test to verify functionality:
func TestNewCurrency(t *testing.T) { c := currency.XYZ // Check basic code string if c.String() != "XYZ" { t.Errorf("Expected currency code 'XYZ', got '%s'", c.String()) } // Test formatting fmt, err := currency.NewFormatter(currency.Locale("en-US")) if err != nil { t.Fatal(err) } formatted := fmt.Format(1234.56, c) t.Logf("Formatted value: %s", formatted) }
Run the package's existing test suite to avoid breaking existing functionality:
go test ./...
- If the currency is a newly approved ISO 4217 code, keep an eye on upstream
x/textupdates—they sync with CLDR releases regularly, so your manual addition might be replaced by an official sync later. - Stick to the package's existing code style and naming conventions to keep changes consistent.
内容的提问来源于stack exchange,提问作者user4466350

