# dustin/go-humanize: number, byte and time formatting for Go output

> A small Go library that turns raw numbers into strings like 83 MB, 1,000,000 and 7 hours ago. It is useful when your program prints values for people rather than for parsers.

**dustin/go-humanize** — Go Humans! (formatters for units to human friendly sizes)

- Repository: https://github.com/dustin/go-humanize
- Website: https://pkg.go.dev/github.com/dustin/go-humanize
- Stars: 4,835 · Forks: 269
- Language: Go
- License: NOASSERTION
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/dustin-go-humanize

## The problem: Go prints numbers the way machines like them

Go's standard formatting verbs are precise and unhelpful to readers. A file size comes out as 82854982, a timestamp as a full RFC 3339 string, a count as 6582491. If your program is a CLI, a log line or a status page, those values are read by people, and people want 83 MB, 7 hours ago and 6,582,491. Writing that conversion yourself means deciding on binary versus decimal units, handling the plural of "day", and getting the ordinal suffix for 11, 12 and 13 right. The README frames the package plainly: "Just a few functions for helping humanize times and sizes." That is the whole scope. It is a formatting library, not a data layer, and it is aimed at Go developers who are already emitting text to a terminal, a log or a web response.

## What the package actually contains: bytes, time, ordinals, commas, SI

The top-level repository entries show the split clearly: bytes.go and bigbytes.go for sizes, times.go for relative timestamps, ordinals.go for 1st and 2nd, comma.go and commaf.go for digit grouping, ftoa.go for float trimming, si.go for metric prefixes, and an english/ subdirectory holding the language-specific helpers. The README's own examples define the behaviour. humanize.Bytes(82854982) returns "83 MB", and the README notes the alternative spelling "79 MiB" for readers who prefer binary units. humanize.Time takes a time.Time and produces "12 seconds ago" or "3 days from now". humanize.Ordinal(193) gives "193rd". humanize.Comma(6582491) gives "6,582,491". humanize.Ftoa(2.24) gives "2.24" where %f would give "2.240000". humanize.SI(0.00000000223, "M") gives "2.23 nM". The english subpackage adds Plural, PluralWord, WordSeries and OxfordWordSeries, with the README showing that Plural(99, "locus", "loci") returns "99 loci" because an explicit irregular form was supplied. Notice how much of this is English-only: the pluralization and word-series functions live behind the english package name, which is an honest signal that the rest of the library is deliberately not locale-aware.

## Installing it and printing a human-readable file size

The README gives the install line directly: fetch it with go get as github.com/dustin/go-humanize, import it as "github.com/dustin/go-humanize", and use it as humanize. The module file confirms the module path and declares go 1.21, so a project on an older toolchain should check that before adding the dependency.

```bash
go get github.com/dustin/go-humanize
```

A first real use is the README's own size example, which prints a byte count through humanize.Bytes with the %s verb.

```go
fmt.Printf("That file is %s.", humanize.Bytes(82854982)) // That file is 83 MB.
```

The README shows the comment on that line as the expected output: That file is 83 MB. The same pattern applies to the other formatters. Swap in humanize.Comma for a count, humanize.Time for a modification timestamp, or humanize.SI when you are printing a value with a metric prefix. Nothing needs configuring and there is no initialisation step.

## Where the library stops: English, display strings, and no configuration

The most consequential limitation is that the output is a presentation string and nothing more. humanize.Bytes(82854982) returns text, so you cannot feed it back into arithmetic, and any consumer that expects a number will need the original value kept separately. The README also exposes no knobs: there is no documented option for choosing binary units globally, no rounding precision setting, and no locale parameter. The english package name is the clearest statement of scope. If your users read German or Japanese, the pluralization and word-series helpers do not apply, and the relative time strings are English words produced by the library. A second boundary is the time formatter itself. It converts a time.Time into a phrase relative to now, which is exactly what you want in a log line and exactly what you do not want in a stored record or an API field that a client will parse. Finally, the repository carries a SECURITY.md and a LICENSE, but the licence is reported as NOASSERTION in the repository metadata and the README does not restate its terms, so anyone embedding this in a distributed product should read the LICENSE file itself rather than rely on a summary.

## How it compares with go-units and with stdlib formatting

The obvious alternative for size formatting is go-units, which people also search for alongside this project. The difference in approach is what each one treats as the source of truth. go-units models a value as a typed quantity with a unit attached, so you can convert between units and carry that unit through your code before formatting at the edge. dustin/go-humanize never models a quantity. It takes an already-computed number and returns a string, which means there is no unit type to pass around and no conversion API to learn, but also no protection against mixing bytes and bits. The other alternative is the standard library alone: fmt with %d, %f and time.Time.Format. That gives you total control and no dependency, at the cost of writing the unit selection, the plural handling and the comma insertion yourself, including the edge cases the README's ordinal table spells out. Pick dustin/go-humanize when the formatting is the only thing you need. Pick go-units when the unit is part of your data model and formatting is a final step.

## Maintenance, licence and the cost of upgrading

The repository is not archived, and the last push was on 2026-09-21, two days before this writing, so the project is receiving changes. The module declares go 1.21, which sets the floor for your toolchain. Upgrading is low-risk in principle because the API surface is a set of free functions with no shared state and no initialisation, so a version bump cannot leave a global half-configured. The real risk sits in the output strings. If a test asserts on "83 MB" or on "7 hours ago", a change to rounding, unit thresholds or wording will break that test, and the README does not promise stability for the exact text. The repository does include fuzz and precision tests, including comma_fuzz_test.go and ftoa_precision_test.go, which suggests the maintainers treat numeric edge cases as a first-class concern. On licensing, the metadata reports NOASSERTION, so the specific terms are whatever the LICENSE file says; that is a question for your own legal review, not something a README summary can settle.

## Conclusion

Adopt dustin/go-humanize if your Go program prints sizes, counts or timestamps for humans and you want that logic out of your own code. Skip it if you need locale-aware formatting, exact decimal arithmetic, or output that downstream machines must parse, since the package returns display strings and the README documents no locale or rounding configuration. Before depending on it, read the godoc for the exact signature of the function you plan to call and check the test coverage report for the parts you rely on.

## FAQ

### What does dustin/go-humanize do?

It is a Go package of formatting helpers that turn raw values into human-readable strings, such as converting 82854982 into 83 MB and a time.Time into 7 hours ago. It also covers ordinals, comma grouping, trimmed floats, SI prefixes and English pluralization.

### How do I install dustin/go-humanize in a Go project?

The README says to go get it as github.com/dustin/go-humanize, import it as "github.com/dustin/go-humanize", and use it as humanize. The module file declares go 1.21.

### Can dustin/go-humanize format a duration or a timestamp for me?

It provides humanize.Time, which takes a time.Time and returns relative wording such as 12 seconds ago or 3 days from now, as shown in the README. That output is a display string, so keep the original time value for anything a program must parse.

### Does dustin/go-humanize support languages other than English?

The pluralization and word-series helpers sit in the humanize/english subpackage, and the README documents no locale parameter for the other formatters. Treat the output as English.

## Sources

- [dustin/go-humanize on GitHub](https://github.com/dustin/go-humanize)
- [Issues](https://github.com/dustin/go-humanize/issues)
- [Project website](https://pkg.go.dev/github.com/dustin/go-humanize)
- [README](https://github.com/dustin/go-humanize/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dustin-go-humanize
