How to Properly Pad Numbers with Zeros in Go: A Formatting Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

The Eternal Problem: "0" on the Left or "Shift Right"?

\n\n

Have you ever wondered why order numbers in SQL queries look like 00042, and in logs like 23:05:07? It's simple: numbers padded with zeros are aligned by width and don't break sorting. But in Go, unlike Python or JavaScript, there is no built-in zfill method. And that's where the fun begins.

\n\n

On Stack Overflow, the question "How to pad a number with zeros when printing?" has garnered thousands of views and dozens of answers. People are looking not just for a solution, but for a fast solution. In this article, we'll break down all the ways to pad a number with zeros in Go, compare their performance, and choose the best one for your project.

\n\n

Why Is This Important for a Go Developer?

\n\n

Go is a language for systems programming, where every nanosecond counts. If you're writing a high-load service, incorrect string formatting can become a bottleneck. Especially if you are formatting thousands of numbers per second.

\n\n
    \n
  • Logging: timestamps, request IDs, error codes.
  • \n
  • Report generation: CSV, JSON, tables.
  • \n
  • Network protocols: fixed field lengths.
  • \n
  • Games and graphics: text alignment in the console.
  • \n
\n\n

Ignoring performance can lead to your service spending 10% of its time just formatting numbers. Don't believe it? Let's check.

\n\n

Method #1: The Classic Way via fmt.Sprintf

\n\n

The most obvious and often recommended way is to use fmt.Sprintf with the format specifier %0Xd, where X is the total width of the number including zeros.

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    num := 42\n    padded := fmt.Sprintf("%05d", num)\n    fmt.Println(padded) // Output: 00042\n}\n
\n\n

Here, %05d means: "print the number as a decimal integer, pad it on the left with zeros to a width of 5 characters". If the number is already longer (e.g., 123456), zeros are not added — the width is ignored.

\n\n

Pros:

\n
    \n
  • Simple and readable.
  • \n
  • Supports negative numbers (the sign will be to the left of the zeros).
  • \n
  • Works with different types: %05d for int, %05.2f for float.
  • \n
\n\n

Cons:

\n
    \n
  • Uses reflection inside fmt — slow.
  • \n
  • Creates an extra string and interface{}.
  • \n
  • Not suitable for hot paths.
  • \n
\n\n

Method #2: Fast strconv.FormatInt with Manual Padding

\n\n

If performance is critical, use the strconv package. It works directly with bytes, without reflection.

\n\n
package main\n\nimport (\n    "fmt"\n    "strconv"\n    "strings"\n)\n\nfunc padNumber(num int64, width int) string {\n    s := strconv.FormatInt(num, 10)\n    if len(s) >= width {\n        return s\n    }\n    return strings.Repeat("0", width-len(s)) + s\n}\n\nfunc main() {\n    fmt.Println(padNumber(42, 5)) // 00042\n}\n
\n\n

Pros:

\n
    \n
  • 2-3 times faster than fmt.Sprintf.
  • \n
  • No reflection.
  • \n
  • Full control over the logic.
  • \n
\n\n

Cons:

\n
    \n
  • More code.
  • \n
  • Need to handle negative numbers separately (sign to the left of zeros).
  • \n
  • strings.Repeat creates a new string — can be further optimized.
  • \n
\n\n

Method #3: Maximum Performance via strings.Builder

\n\n

For those who want to squeeze out every last drop of performance, there is a way without unnecessary allocations — use strings.Builder and pre-allocate the buffer.

\n\n
package main\n\nimport (\n    "fmt"\n    "strconv"\n    "strings"\n)\n\nfunc padNumberFast(num int64, width int) string {\n    s := strconv.FormatInt(num, 10)\n    if len(s)                

Blogs

Book Recommendations