HowtoGo
Home / Notes / Format Verb Notes
Notes

Format Verb Notes

Every fmt function and formatting verb in one place: what each call returns, what each verb prints, and the interfaces that change the output.

A lookup sheet for fmt. Every example is one expression and the exact text it prints under Go 1.26. For the package itself, with runnable examples, see the fmt package guide.

Functions

Printing
VerbPrintsExample
PrintWrites to standard output. Adds a space only between two operands that are both non-strings.
fmt.Print("a", "b", 1, 2) ab1 2
PrintlnWrites to standard output with spaces between every operand and a trailing newline.
fmt.Println("a", "b", 1) a b 1
PrintfWrites to standard output using a format string. Adds no newline.
fmt.Printf("%s=%d", "n", 1) n=1
SprintThe same as Print, returned as a string.
fmt.Sprint("a", 1, 2) a1 2
SprintlnThe same as Println, returned as a string with its newline.
fmt.Sprintln("a", 1) a 1\n
SprintfThe same as Printf, returned as a string. The one you reach for most.
fmt.Sprintf("%05.2f", 3.14159) 03.14
FprintPrint, aimed at any io.Writer.
fmt.Fprint(w, "a", 1) a1
FprintlnPrintln, aimed at any io.Writer.
fmt.Fprintln(os.Stderr, "up") up
FprintfPrintf, aimed at any io.Writer. This is how you write to a file, a socket, or a response.
fmt.Fprintf(w, "%d%%", 50) 50%
ErrorfBuilds an error. The only place %w works, which wraps an error so errors.Is can still find it.
fmt.Errorf("load: %w", err) load: boom
AppendAppends the Sprint form to a byte slice.
fmt.Append(b, 1, "a") []byte("1a")
AppendfAppends the Sprintf form to a byte slice, with no allocation of a new string.
fmt.Appendf(b, "%d", 42) []byte("42")
Reading back
VerbPrintsExample
ScanReads space-separated values from standard input into pointers. Newlines count as spaces.
fmt.Scan(&a, &b) n, err
ScanlnLike Scan, but stops at a newline.
fmt.Scanln(&name) n, err
ScanfReads standard input against a format string.
fmt.Scanf("%d-%d", &a, &b) n, err
SscanThe same, reading from a string instead of standard input.
fmt.Sscan("3 4", &a, &b) 2, nil
SscanfParses a string against a format string.
fmt.Sscanf("3-4", "%d-%d", &a, &b) 2, nil
FscanReads from any io.Reader.
fmt.Fscan(r, &a) n, err
FscanfReads from any io.Reader against a format string.
fmt.Fscanf(r, "%s", &s) n, err

Verbs

General
VerbPrintsExample
%vDefault format. Calls String() when the type has one.
Printf("%v", p) {3 4}
%+vLike %v, with struct field names.
Printf("%+v", p) {X:3 Y:4}
%#vGo syntax for the value, type name included.
Printf("%#v", p) main.Point{X:3, Y:4}
%TGo syntax for the value's type.
Printf("%T", p) main.Point
%pPointer address in hex, prefixed 0x.
Printf("%p", &x) 0xc0000140a0
%%A literal percent sign. Consumes no operand.
Printf("%d%%", 50) 50%
Booleans and integers
VerbPrintsExample
%dBase 10.
Printf("%d", 42) 42
%bBase 2.
Printf("%b", 5) 101
%oBase 8.
Printf("%o", 9) 11
%OBase 8 with a 0o prefix.
Printf("%O", 9) 0o11
%xBase 16, lower case.
Printf("%x", 255) ff
%XBase 16, upper case.
Printf("%X", 255) FF
%cThe character at that code point.
Printf("%c", 9731)
%qA single-quoted character literal, escaped.
Printf("%q", 9731) '☃'
%UUnicode notation.
Printf("%U", 9731) U+2603
%#UUnicode notation with the character.
Printf("%#U", 9731) U+2603 '☃'
%tA bool, as true or false.
Printf("%t", true) true
Floating point
VerbPrintsExample
%fDecimal, no exponent. Six digits by default.
Printf("%f", 3.14159) 3.141590
%.2fDecimal, precision set explicitly.
Printf("%.2f", 3.14159) 3.14
%eScientific notation, lower case.
Printf("%e", 123456.789) 1.234568e+05
%EScientific notation, upper case.
Printf("%E", 123456.789) 1.234568E+05
%g%e for large exponents, %f otherwise. Drops trailing zeros.
Printf("%g", 123456.789) 123456.789
%gThe same verb on a small number.
Printf("%g", 0.00001234) 1.234e-05
%xHexadecimal floating point.
Printf("%x", 3.14159) 0x1.921f9f01b866ep+01
Strings and byte slices
VerbPrintsExample
%sThe string, or the bytes, as they are.
Printf("%s", "héllo") héllo
%qDouble-quoted and escaped, safe to paste back into Go.
Printf("%q", "héllo") "héllo"
%.2sTruncated. Precision on a string is a maximum length.
Printf("%.2s", "hello") he
%xEach byte in hex, lower case.
Printf("%x", "héllo") 68c3a96c6c6f
% xHex with a space between bytes.
Printf("% x", "héllo") 68 c3 a9 6c 6c 6f
%XEach byte in hex, upper case.
Printf("%X", "héllo") 68C3A96C6C6F
%vOn a []byte this is the numbers, not the text.
Printf("%v", []byte("abc")) [97 98 99]
%sOn a []byte this is the text.
Printf("%s", []byte("abc")) abc
Width, precision, and flags
VerbPrintsExample
-Pad on the right instead of the left.
Printf("%-6d|", 42) 42 |
+Always show a sign. On %v it adds struct field names.
Printf("%+d", 42) +42
0Pad numbers with leading zeros rather than spaces.
Printf("%05d", 42) 00042
spaceA space for the sign of a positive number, or between hex bytes.
Printf("% x", "hé") 68 c3 a9
#Alternate form: 0o, 0x, Go syntax on %v.
Printf("%#U", 9731) U+2603 '☃'
6Minimum width. Pads, never truncates.
Printf("%8s|", "hi") hi|
.2Precision: digits after the point, or a string's maximum length.
Printf("%8.2f|", 3.14159) 3.14|
*Take the width from the argument list.
Printf("%*d", 6, 42) 42
.*Take the precision from the argument list.
Printf("%.*f", 2, 3.14159) 3.14
[n]Use the nth argument. Later verbs continue from there.
Printf("%[2]d %[1]d", 1, 2) 2 1
What a broken format string prints
VerbPrintsExample
%!verbThe verb does not apply to that type.
Sprintf("%d", "hi") %!d(string=hi)
MISSINGMore verbs than arguments.
Sprintf("%d %d", 1) 1 %!d(MISSING)
EXTRAMore arguments than verbs.
Sprintf("%d", 1, 2) 1%!(EXTRA int=2)
%!yNo such verb.
Sprintf("%y", 1) %!y(int=1)

Interfaces that change the output

FunctionDescription
Stringer interface { String() string }
func (t Temp) String() string
Controls %v and %s for the type.
GoStringer interface { GoString() string }
Controls %#v for the type.
Formatter interface { Format(f State, verb rune) }
Takes over every verb for the type.
error interface { Error() string }
Printed by %v and %s when the type has no String method.

Picking a verb

%v for logs, %+v when a struct is empty-looking

%v on a struct prints {3 4}, which tells you nothing about which field is which. %+v prints {X:3 Y:4}. In a log line that difference is the whole message.

%q whenever whitespace could be the bug

%s renders "hi " and "hi" identically. %q quotes and escapes, so a trailing space, a tab, or a stray \r becomes visible.

%T when a type assertion or an interface surprises you

%T prints the dynamic type, which is the fastest way to find out what actually came out of a map[string]any or a JSON decode.

%w in Errorf, never %v

%w wraps the error so errors.Is and errors.As can still find it. %v flattens it to text and breaks both. Only Errorf accepts %w.

%d on a []byte does not do what it looks like

%s gives the text and %v gives the numbers. There is no verb that prints a byte slice as text with quotes except %q.

Print adds spaces between operands only when neither is a string

Println always separates and always adds a newline. Print does neither reliably, which is why a Print call often produces runtogethertext.

Sprintf in a String method is a recursion trap

fmt.Sprintf("%v", t) inside func (t Temp) String() calls String again. Convert first: fmt.Sprintf("%.1f", float64(t)).

go vet checks format strings

A mismatched verb, a missing argument, and an extra argument are all reported by go vet, which runs as part of go test. The %!d(string=hi) forms above are what reaches production when it is skipped.