go 50 lines · 8 steps

Parsing human-readable byte sizes in Go

A regex plus a lookup table turn strings like "1.5gb" into an exact byte count.

Explained by highlit
1package humanize
2 
3import (
4 "fmt"
5 "math"
6 "regexp"
7 "strconv"
8 "strings"
9)
10 
11var sizePattern = regexp.MustCompile(`(?i)^\s*([0-9]*\.?[0-9]+)\s*([kmgtpe]?i?b?)\s*$`)
12 
13var unitFactors = map[string]uint64{
14 "": 1,
15 "b": 1,
16 "kb": 1000, "mb": 1000 * 1000, "gb": 1000 * 1000 * 1000,
17 "tb": 1000 * 1000 * 1000 * 1000,
18 "pb": 1000 * 1000 * 1000 * 1000 * 1000,
19 "kib": 1 << 10, "mib": 1 << 20, "gib": 1 << 30,
20 "tib": 1 << 40, "pib": 1 << 50,
21}
22 
23func ParseBytes(s string) (uint64, error) {
24 matches := sizePattern.FindStringSubmatch(s)
25 if matches == nil {
26 return 0, fmt.Errorf("humanize: invalid size %q", s)
27 }
28 
29 num, err := strconv.ParseFloat(matches[1], 64)
30 if err != nil {
31 return 0, fmt.Errorf("humanize: invalid number in %q: %w", s, err)
32 }
33 
34 unit := strings.ToLower(matches[2])
35 if unit != "" && unit != "b" && !strings.HasSuffix(unit, "b") {
36 unit += "b"
37 }
38 
39 factor, ok := unitFactors[unit]
40 if !ok {
41 return 0, fmt.Errorf("humanize: unknown unit %q", matches[2])
42 }
43 
44 bytes := num * float64(factor)
45 if bytes < 0 || bytes > math.MaxUint64 {
46 return 0, fmt.Errorf("humanize: size %q out of range", s)
47 }
48 
49 return uint64(bytes), nil
50}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1A precompiled regex with capture groups cleanly separates a numeric value from its unit suffix.
  2. 2A map of unit-to-multiplier keeps decimal (kb) and binary (kib) scaling declarative instead of buried in branches.
  3. 3Validating the float range before converting to uint64 prevents silent overflow on out-of-range input.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Parsing human-readable byte sizes in Go — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code