Arbitrary-precision fixed-point decimal numbers for Go, avoiding floating-point precision issues with support for arithmetic, rounding, serialization, and database integration.
Decimal implements multiple serialization interfaces: JSON, text (XML), binary, Gob encoding, and database (database/sql) integration. NullDecimal implements JSON, text, and database interfaces.
By default, Decimal marshals to JSON as a quoted string to preserve precision. Set MarshalJSONWithoutQuotes = true to marshal as a number.
// MarshalJSON implements json.Marshaler.
// Default: outputs quoted string (e.g., "3.14").
// If MarshalJSONWithoutQuotes is true: outputs unquoted number (e.g., 3.14).
func (d Decimal) MarshalJSON() ([]byte, error)
// UnmarshalJSON implements json.Unmarshaler.
// Accepts both quoted strings and unquoted numbers.
func (d *Decimal) UnmarshalJSON(decimalBytes []byte) errorUsage:
import (
"encoding/json"
"github.com/shopspring/decimal"
)
// Struct with Decimal field
type Price struct {
Amount decimal.Decimal `json:"amount"`
}
// Marshal (default: quoted)
p := Price{Amount: decimal.NewFromFloat(19.99)}
data, _ := json.Marshal(p)
// data: {"amount":"19.99"}
// Unmarshal
var p2 Price
json.Unmarshal([]byte(`{"amount":"19.99"}`), &p2)
json.Unmarshal([]byte(`{"amount":19.99}`), &p2) // also works
// Marshal as number (configure globally)
decimal.MarshalJSONWithoutQuotes = true
data2, _ := json.Marshal(p)
// data2: {"amount":19.99}Implements encoding.TextMarshaler / encoding.TextUnmarshaler, used by encoding/xml and other text-based formats.
// MarshalText implements encoding.TextMarshaler.
// Returns the decimal as a text byte slice (same as String()).
func (d Decimal) MarshalText() (text []byte, err error)
// UnmarshalText implements encoding.TextUnmarshaler.
// Parses the text byte slice as a decimal string.
func (d *Decimal) UnmarshalText(text []byte) errorUsage:
import "encoding/xml"
type Item struct {
Price decimal.Decimal `xml:"price"`
}
// XML marshal/unmarshal
item := Item{Price: decimal.NewFromFloat(9.99)}
data, _ := xml.Marshal(item)
// data: <Item><price>9.99</price></Item>
var item2 Item
xml.Unmarshal(data, &item2)
// item2.Price = 9.99// MarshalBinary implements encoding.BinaryMarshaler.
// Stores the decimal as its string representation as []byte.
func (d Decimal) MarshalBinary() (data []byte, err error)
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
// Parses the binary data as a decimal string.
func (d *Decimal) UnmarshalBinary(data []byte) errorUsage:
d := decimal.NewFromFloat(3.14)
data, err := d.MarshalBinary() // []byte("3.14")
var d2 decimal.Decimal
err = d2.UnmarshalBinary(data)
// d2 = 3.14// GobEncode implements encoding.GobEncoder.
func (d Decimal) GobEncode() ([]byte, error)
// GobDecode implements encoding.GobDecoder.
func (d *Decimal) GobDecode(data []byte) errorUsage:
import (
"bytes"
"encoding/gob"
)
// Encode
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
d := decimal.NewFromFloat(3.14)
enc.Encode(d)
// Decode
var d2 decimal.Decimal
dec := gob.NewDecoder(&buf)
dec.Decode(&d2)Decimal implements sql.Scanner and driver.Valuer for seamless use with Go's database/sql package. Stores and retrieves decimals as strings.
// Scan implements sql.Scanner for database deserialization.
// Accepts string, []byte, and other numeric types from the database driver.
func (d *Decimal) Scan(value interface{}) error
// Value implements driver.Valuer for database serialization.
// Returns the decimal as a string driver.Value.
func (d Decimal) Value() (driver.Value, error)Usage:
import (
"database/sql"
_ "github.com/lib/pq" // or other driver
)
// In struct tags
type Product struct {
ID int
Price decimal.Decimal
}
// Query with scanning
db, _ := sql.Open("postgres", "...")
var p Product
row := db.QueryRow("SELECT id, price FROM products WHERE id = $1", 1)
err := row.Scan(&p.ID, &p.Price)
// Insert
_, err = db.Exec("INSERT INTO products (price) VALUES ($1)", p.Price)Install with Tessl CLI
npx tessl i tessl/golang-github-com-shopspring--decimal@1.4.1