Menu

Golang Printf and Sprintf: fmt Format Verbs Cheat Sheet

How Go's fmt package prints and formats values: Println vs Printf vs Sprintf vs Errorf, the full table of format verbs (%v, %+v, %d, %s, %q, %f, %T, %w and more), width, precision and padding.

This page includes runnable editors - edit, run, and see output instantly.

The fmt package has three families of print functions, and each family has the same three variants:

FunctionOutput goes toFormat
Print, Println, Printfstandard outputdefault, default with spaces and newline, format string
Sprint, Sprintln, Sprintfa returned stringsame three styles
Fprint, Fprintln, Fprintfany io.Writer (file, buffer, HTTP response)same three styles
Errorfa returned errorformat string, plus %w for wrapping

Println adds spaces between operands and a newline at the end. Printf adds nothing: you write \n yourself. Print adds spaces only between operands that are both non-strings, which is surprising enough that most code uses Println or Printf.

Format Verbs

General

VerbPrintsExample output
%vthe value in a default format{Ana 31 [admin]}
%+vstructs with field names{Name:Ana Age:31 Tags:[admin]}
%#vGo syntax for the valuemain.User{Name:"Ana", Age:31, Tags:[]string{"admin"}}
%Tthe typemain.User
%%a literal percent sign%

%+v is the one to reach for when debugging. A pointer to a struct prints as &{...} rather than an address. Maps print with keys sorted, so output is stable even though map iteration order is random.

Integers

VerbMeaningfmt.Sprintf(verb, 255)
%ddecimal255
%bbinary11111111
%ooctal377
%Ooctal with 0o prefix0o377
%x / %Xhex, lower or upper caseff / FF
%#xhex with 0x prefix0xff
%cthe character with that code pointÿ
%qa quoted character literal'ÿ'
%UUnicode formatU+00FF

Floats

VerbMeaningfmt.Sprintf(verb, 1234.5678)
%fdecimal, 6 places by default1234.567800
%.2fdecimal, 2 places1234.57
%escientific notation1.234568e+03
%g%e or %f, whichever is shorter, no trailing zeros1234.5678
%vsame as %g1234.5678

%.2f rounds the float's exact binary value, so fmt.Sprintf("%.2f", 2.675) is 2.67: the nearest float64 to 2.675 is slightly below it. Never format money from a float; keep cents in an integer.

Strings and bytes

VerbMeaningfmt.Sprintf(verb, "go\n")
%sthe plain stringgo and a newline
%qdouble-quoted, escapes shown"go\n"
%xhex of each byte676f0a
% xhex with spaces67 6f 0a

%s on a []byte prints it as text; %v prints the numbers ([104 105]).

Other types

VerbTypePrints
%tbooltrue or false
%ppointer, slice, map, channel, functhe address, like 0xc000012345
%werror (only in Errorf)the error's message, and wraps it

Width, Precision and Padding

Between % and the verb you can put flags, a width and a precision:

FormEffect
%5dwidth 5, right-aligned (pad on the left with spaces)
%-5dwidth 5, left-aligned
%05dpad with zeros
%.2f2 digits after the decimal point
%8.2fwidth 8 and 2 decimals
%.3sat most 3 characters of the string
%+dalways show the sign
%*dwidth taken from the next argument

Note %.0f of 2.5 prints 2: Go rounds half to even here. Width counts runes for strings, not display columns, so CJK characters and emoji can still misalign a table. For aligned columns of variable text, text/tabwriter does the measuring for you.

Argument indexes

%[n] picks an argument by position, which lets you reuse one:

fmt.Printf("%[2]s %[1]s\n", "world", "hello") // hello world
fmt.Printf("%d %[1]x %[1]b\n", 10)             // 10 a 1010

Errorf and %w

fmt.Errorf builds an error from a format string. With %w it also wraps another error, so callers can still detect the original:

Use %w when callers may need to check the cause, and %v when you deliberately hide it. Since Go 1.20 one Errorf call may contain several %w verbs. The error handling page covers wrapping in depth.

Custom Formatting with String()

Any type with a String() string method controls how %v, %s and Println show it:

%d bypasses String() and prints the underlying number. For error types the equivalent method is Error() string, which takes precedence over String().

When the Verb Is Wrong

fmt never panics on a bad format. It prints the problem inline:

fmt.Printf("%d\n", "oops")
fmt.Printf("%d %d\n", 1)
fmt.Printf("%d\n", 1, 2)
%!d(string=oops)
1 %!d(MISSING)
1
%!(EXTRA int=2)

That output tends to reach production because it does not crash anything. go vet catches all three at build time:

./main.go:8:2: fmt.Printf format %d has arg "oops" of wrong type string
./main.go:9:2: fmt.Printf format %d reads arg #2, but call has 1 arg
./main.go:10:2: fmt.Printf call needs 1 arg but has 2 args

Performance Notes

fmt takes every argument as an any and inspects its type at run time (falling back to reflection for structs, slices and maps), which is fine for logging and output but measurable in tight loops. For converting a single number, strconv.Itoa and strconv.FormatFloat are faster than Sprintf. For building a long string in a loop, write into a strings.Builder with fmt.Fprintf(&b, ...) instead of concatenating Sprintf results.

Frequently Asked Questions

What is the difference between Println, Printf and Sprintf in Go?

fmt.Println prints its arguments separated by spaces with a newline at the end. fmt.Printf prints according to a format string and adds no newline. fmt.Sprintf formats the same way as Printf but returns the result as a string instead of printing it. fmt.Errorf does the same and returns an error.

How do I print a struct with field names in Go?

Use %+v: fmt.Printf("%+v\n", user) prints {Name:Ana Age:31}. %v prints only the values, {Ana 31}, and %#v prints Go syntax including the type, main.User{Name:"Ana", Age:31}.

How do I format a float to 2 decimal places in Go?

Use %.2f: fmt.Sprintf("%.2f", 3.14159) returns "3.14". Add a width to align columns, %8.2f, or a minus sign to left-align, %-8.2f. strconv.FormatFloat(f, 'f', 2, 64) gives the same result without a format string.

What does %w do in fmt.Errorf?

%w formats an error like %v and also wraps it, so the new error carries the original. errors.Is and errors.As can then find the wrapped error: err := fmt.Errorf("load config: %w", os.ErrNotExist) makes errors.Is(err, os.ErrNotExist) true. %w only works in fmt.Errorf.

Why does my output show %!d(string=...)?

The verb does not match the argument's type, for example %d given a string. fmt prints the problem inline instead of panicking: %!d(string=oops). Missing arguments print %!d(MISSING) and extra ones %!(EXTRA int=2). go vet catches all three before you run the program.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED