Go October 5, 2024 Aditya Rawas

Demystifying Go's fmt.Sprintf: A Practical Guide

Go’s fmt.Sprintf() is rooted in C’s printf and scanf family of functions. While C developers may find it familiar, developers coming from other languages sometimes find the syntax confusing. This guide breaks down everything you need to know to use fmt.Sprintf() — and the broader fmt package — with confidence.


Printf-Like Functions in Go

fmt.Sprintf() is just one of many Printf-style functions in Go. Others you’ll encounter include:

Most principles in this guide apply to all of them.


1. Why Use fmt.Sprintf()?

Even if the syntax looks unfamiliar at first, fmt.Sprintf() is worth learning. It separates constant string structure from variable content, making code far more readable.

Without fmt.Sprintf():

myString := "Results: " + results + " and more: " + more + "."

With fmt.Sprintf():

myString := fmt.Sprintf("Results: %s and more: %s.", results, more)

Clean, predictable, and easy to extend.


2. Avoid Mixing Concatenation and fmt.Sprintf()

Mixing string concatenation (+) with fmt.Sprintf() isn’t a syntax error, but it creates messy, hard-to-maintain code.

Bad:

fmt.Sprintf("Format %s " + name + "... Stuff %d", f, 5)

Good:

fmt.Sprintf("Format %s %s... Stuff %d", f, name, 5)

Pick one approach and stick with it. fmt.Sprintf() is almost always the better choice.


3. The Top 5 Format Verbs

Format specifiers (called verbs in Go) tell fmt.Sprintf() how to format each argument.

%v — The “anything” verb

Works with almost any type. Great for quick debugging.

a, b, c := 5, "Hello", false
fmt.Printf("%v %v %v", a, b, c) // Output: 5 Hello false

%s — String

Formats a value as a plain string.

a := "Golang"
fmt.Printf("Language: %s\n", a) // Output: Language: Golang

%q — Quoted string

Adds double quotes around the value — useful for debugging and logging.

a := "Hello"
fmt.Printf("%q\n", a) // Output: "Hello"

%d — Integer (base-10)

Formats integer values in decimal.

a := 123
fmt.Printf("%d\n", a) // Output: 123

%t — Boolean

Formats true or false.

a := true
fmt.Printf("%t\n", a) // Output: true

For the full list of verbs, see the official fmt documentation.


4. Argument Indexing

One of the most powerful features of fmt.Sprintf() is argument indexing — referencing arguments by position using [n] before the verb.

red, blue, orange := "Red", "Blue", "Orange"
fmt.Printf("%[1]s %[3]s %[2]s\n", red, orange, blue)
// Output: Red Blue Orange

Here:

This is especially useful when the same value needs to appear multiple times in a format string without repeating it in the argument list.

a, b, c := "Do", "De", "Da"
fmt.Printf("%[2]s %[1]s %[3]s\n", a, b, c)
// Output: De Do Da

5. Common Errors and How to Fix Them

Wrong type for the verb

// Error: format has argument of wrong type
fmt.Printf("%d\n", "Hello")

// Fix:
fmt.Printf("%s\n", "Hello") // Output: Hello

Too many arguments

// Error: too many arguments
fmt.Printf("%d %d", 3, 2, 1)

// Fix:
fmt.Printf("%d %d", 3, 2) // Output: 3 2

Too few arguments

// Error: not enough arguments
fmt.Printf("%s")

// Fix:
fmt.Printf("%s", "Hello") // Output: Hello

Non-integer for width/precision

// Error: width requires an int
fmt.Printf("%*s", 10.5, "hi")

// Fix:
fmt.Printf("%*s", 10, "hi") // Output:         hi

Invalid argument index

// Error: invalid argument index
fmt.Printf("%[2]s", "a")

// Fix:
fmt.Printf("%[1]s", "a") // Output: a

Key Takeaways