numberformat

package module
v0.0.0-...-ba66c1a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 4 Imported by: 0

README

go-numberformat

CI Go Reference Go Report Card

A zero-dependency Go library for formatting numbers (int, float, string) into human-readable strings with support for thousands separators, decimal precision, currency symbols, and multiple locales.

Features

  • ✅ Accepts int, float, and string input
  • ✅ Thousands separator formatting
  • ✅ Configurable decimal precision
  • ✅ Currency formatting with symbol positioning
  • ✅ Multi-locale support (ID, EN, DE, GB, JP — or custom)
  • ✅ Negative number styles: minus (-) or parenthesis (())
  • ✅ Zero external dependencies
  • ✅ Functional options pattern for clean API

Requirements

  • Go 1.21+

Installation

go get github.com/dsdhanidev/go-numberformat

Quick Start

package main

import (
    "fmt"
    numfmt "github.com/dsdhanidev/go-numberformat"
)

func main() {
    // Basic number formatting (EN locale by default)
    result, _ := numfmt.Number(1000000)
    fmt.Println(result) // 1,000,000.00

    // Indonesian locale
    result, _ = numfmt.Number(1234567.89, numfmt.WithLocale(numfmt.LocaleID))
    fmt.Println(result) // 1.234.567,89

    // Currency - IDR
    result, _ = numfmt.Currency(1500000, numfmt.WithLocale(numfmt.LocaleID))
    fmt.Println(result) // Rp 1.500.000,00

    // Currency - USD
    result, _ = numfmt.Currency(9.99, numfmt.WithLocale(numfmt.LocaleEN))
    fmt.Println(result) // $9.99

    // From string input
    result, _ = numfmt.Number("2500000", numfmt.WithLocale(numfmt.LocaleID))
    fmt.Println(result) // 2.500.000,00
}

API

Number(value any, opts ...Option) (string, error)

Formats any numeric value into a number string.

numfmt.Number(1000)                                          // "1,000.00"
numfmt.Number(float64(1234.56))                              // "1,234.56"
numfmt.Number("500000", numfmt.WithLocale(numfmt.LocaleID)) // "500.000,00"
Currency(value any, opts ...Option) (string, error)

Formats any numeric value as a currency string.

numfmt.Currency(1500000, numfmt.WithLocale(numfmt.LocaleID)) // "Rp 1.500.000,00"
numfmt.Currency(9.99, numfmt.WithLocale(numfmt.LocaleEN))    // "$9.99"
numfmt.Currency(1234.56, numfmt.WithLocale(numfmt.LocaleDE)) // "1.234,56 €"
MustNumber / MustCurrency

Panic-on-error variants for use when input type is guaranteed valid.

result := numfmt.MustNumber(1000000)
result := numfmt.MustCurrency(50000, numfmt.WithLocale(numfmt.LocaleID))

Options

Option Description Default
WithLocale(locale) Set the locale LocaleEN
WithPrecision(n) Number of decimal places 2
WithNegativeStyle(style) NegativeStyleMinus or NegativeStyleParenthesis NegativeStyleMinus
WithNoThousandSep() Disable thousands separator false

Locales

Variable Thousand Decimal Currency Example
LocaleID . , Rp (prefix) Rp 1.000.000,00
LocaleEN , . $ (prefix) $1,000,000.00
LocaleDE . , (suffix) 1.000.000,00 €
LocaleGB , . £ (prefix) £1,000,000.00
LocaleJP , . ¥ (prefix) ¥1,000,000
Custom Locale
myLocale := numfmt.Locale{
    ThousandSep:            "_",
    DecimalSep:             ".",
    CurrencySymbol:         "BTC",
    CurrencySymbolPosition: "suffix",
    CurrencySymbolSpace:    true,
}

result, _ := numfmt.Currency(0.00123456, numfmt.WithLocale(myLocale), numfmt.WithPrecision(8))
// => "0.00123456 BTC"

Negative Number Styles

// Minus style (default)
numfmt.Number(-1000, numfmt.WithNegativeStyle(numfmt.NegativeStyleMinus))
// => "-1,000.00"

// Parenthesis style
numfmt.Number(-1000, numfmt.WithNegativeStyle(numfmt.NegativeStyleParenthesis))
// => "(1,000.00)"

Development

Run tests
go test -v -race ./...
Run tests with coverage
go test -v -race -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
Using Docker
# Run tests
docker compose run --rm test

# Enter dev shell
docker compose run --rm dev
Benchmark
go test -bench=. -benchmem ./...

Contributing

Contributions are welcome! Please open an issue first to discuss what you would like to change. Make sure to update tests as appropriate.

License

MIT

Documentation

Overview

Package numberformat provides utilities to format numbers (int, float, string) into human-readable string representations with support for thousands separators, decimal precision, currency symbols, and multiple locales.

Example usage:

// Format an integer with default options (EN locale)
result := numberformat.Number(1000000)
// result: "1,000,000"

// Format a float with Indonesian locale
result := numberformat.Number(1234567.89, numberformat.WithLocale(numberformat.LocaleID))
// result: "1.234.567,89"

// Format as currency
result := numberformat.Currency(1500000, numberformat.WithLocale(numberformat.LocaleID))
// result: "Rp 1.500.000,00"

Index

Constants

This section is empty.

Variables

View Source
var (
	// LocaleID is the Indonesian locale (e.g. 1.000.000,50 | Rp 1.000.000,50)
	LocaleID = Locale{
		ThousandSep:            ".",
		DecimalSep:             ",",
		CurrencySymbol:         "Rp",
		CurrencySymbolPosition: "prefix",
		CurrencySymbolSpace:    true,
	}

	// LocaleEN is the English (US) locale (e.g. 1,000,000.50 | $ 1,000,000.50)
	LocaleEN = Locale{
		ThousandSep:            ",",
		DecimalSep:             ".",
		CurrencySymbol:         "$",
		CurrencySymbolPosition: "prefix",
		CurrencySymbolSpace:    false,
	}

	// LocaleDE is the German locale (e.g. 1.000.000,50 | 1.000.000,50 €)
	LocaleDE = Locale{
		ThousandSep:            ".",
		DecimalSep:             ",",
		CurrencySymbol:         "€",
		CurrencySymbolPosition: "suffix",
		CurrencySymbolSpace:    true,
	}

	// LocaleGB is the British locale (e.g. 1,000,000.50 | £1,000,000.50)
	LocaleGB = Locale{
		ThousandSep:            ",",
		DecimalSep:             ".",
		CurrencySymbol:         "£",
		CurrencySymbolPosition: "prefix",
		CurrencySymbolSpace:    false,
	}

	// LocaleJP is the Japanese locale (e.g. 1,000,000 | ¥1,000,000)
	LocaleJP = Locale{
		ThousandSep:            ",",
		DecimalSep:             ".",
		CurrencySymbol:         "¥",
		CurrencySymbolPosition: "prefix",
		CurrencySymbolSpace:    false,
	}
)

Functions

func Currency

func Currency(value any, opts ...Option) (string, error)

Currency formats any numeric value as a currency string using the locale's currency symbol and formatting rules.

Example:

numberformat.Currency(1500000, numberformat.WithLocale(numberformat.LocaleID))
// => "Rp 1.500.000,00"

numberformat.Currency(9.99, numberformat.WithLocale(numberformat.LocaleEN))
// => "$9.99"

func MustCurrency

func MustCurrency(value any, opts ...Option) string

MustCurrency is like Currency but panics on error.

func MustNumber

func MustNumber(value any, opts ...Option) string

MustNumber is like Number but panics on error. Use this when the input type is guaranteed to be valid.

func Number

func Number(value any, opts ...Option) (string, error)

Number formats any numeric value (int, float, string) into a formatted string. It accepts int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, and string types.

Example:

numberformat.Number(1000000)
// => "1,000,000"

numberformat.Number(1234.5, numberformat.WithLocale(numberformat.LocaleID), numberformat.WithPrecision(2))
// => "1.234,50"

Types

type Locale

type Locale struct {
	// ThousandSep is the separator used for thousands grouping (e.g. "." or ",")
	ThousandSep string
	// DecimalSep is the separator used for decimal point (e.g. "," or ".")
	DecimalSep string
	// CurrencySymbol is the symbol used for currency formatting (e.g. "Rp", "$")
	CurrencySymbol string
	// CurrencySymbolPosition defines where the symbol is placed: "prefix" or "suffix"
	CurrencySymbolPosition string
	// CurrencySymbolSpace defines whether there is a space between symbol and number
	CurrencySymbolSpace bool
}

Locale defines the formatting rules for a specific locale.

type NegativeStyle

type NegativeStyle int

NegativeStyle defines how negative numbers are displayed.

const (
	// NegativeStyleMinus displays negative numbers with a minus sign (e.g. -1.000)
	NegativeStyleMinus NegativeStyle = iota
	// NegativeStyleParenthesis displays negative numbers with parentheses (e.g. (1.000))
	NegativeStyleParenthesis
)

type Option

type Option func(*Options)

Option is a functional option for configuring formatting.

func WithLocale

func WithLocale(locale Locale) Option

WithLocale sets the locale for formatting.

func WithNegativeStyle

func WithNegativeStyle(style NegativeStyle) Option

WithNegativeStyle sets the style for negative numbers.

func WithNoThousandSep

func WithNoThousandSep() Option

WithNoThousandSep disables the thousands separator.

func WithPrecision

func WithPrecision(precision int) Option

WithPrecision sets the number of decimal places.

type Options

type Options struct {
	// Locale defines the locale to use for formatting.
	// Defaults to LocaleEN if not set.
	Locale Locale
	// Precision is the number of decimal places to display.
	// Defaults to 2.
	Precision int
	// NegativeStyle defines how negative numbers are displayed.
	// Defaults to NegativeStyleMinus.
	NegativeStyle NegativeStyle
	// NoThousandSep disables the thousands separator.
	NoThousandSep bool
}

Options defines the formatting options.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL