fmt

Guided tour · Formatting & Strings · pkg.go.dev →

Formatted I/O: Print, Printf, Sprintf, Scan, Errorf. Go's go-to for building and parsing text.

Format text and values. Reach for fmt to print, build error messages, render structs while debugging, or scan simple input.

Print a value
fmt.Println(x)
Print to stderr
fmt.Fprintln(os.Stderr, "warning:", msg)
Format into a string
s := fmt.Sprintf("user=%d", id)
Build a wrapped error
err := fmt.Errorf("open %q: %w", path, err)
Show a struct with field names
fmt.Printf("%+v\n", point)
Show Go-syntax (debug)
fmt.Printf("%#v\n", point)
Type of a value
fmt.Printf("%T\n", x)
Hex / binary
fmt.Printf("%x %b\n", n, n)

The three print families

Each family comes in three flavors: no suffix (no newline), ln (adds spaces between args and a newline), and f (format string). They also come with prefixes: nothing (stdout), S (return string), F (write to any io.Writer), and Errorf (returns an error).

Println — spaces between args, newline at end

fmt.Println("hello", "world", 42)
fmt.Println() // blank line
Output
hello world 42

Print — no spaces between args unless they're both strings

Print inserts a space between two non-string operands. It does NOT add a newline.

fmt.Print("a", "b")      // no space: ab
fmt.Print(1, 2)          // space:   1 2
fmt.Print("x", 7, "y\n") // mixed:  x7 y
Output
ab1 2x7 y

Printf — explicit format string

fmt.Printf("%s is %d years old\n", "Ada", 36)
Output
Ada is 36 years old

Sprintf — format into a string

Use Sprintf when you want the result as a string (e.g., for logging, building messages).

msg := fmt.Sprintf("user=%s id=%d", "ada", 7)
fmt.Println(msg)
Output
user=ada id=7

Fprintf — write to any io.Writer

F-variants take an io.Writer first. Use with os.Stderr, files, bytes.Buffer, http.ResponseWriter, etc.

fmt.Fprintf(os.Stderr, "warning: %s\n", "disk almost full")

var buf bytes.Buffer
fmt.Fprintf(&buf, "line %d\n", 1)
fmt.Print(buf.String())
Output
line 1

Errorf — build an error

Use %w to wrap another error so errors.Is and errors.As work.

err := fmt.Errorf("open %q: %w", "/tmp/x", os.ErrNotExist)
fmt.Println(err)
fmt.Println(errors.Is(err, os.ErrNotExist))
Output
open "/tmp/x": file does not exist
true

The common verbs

Verbs begin with % and describe how to format an argument.

%v, %+v, %#v — the general verbs

%v is the default. %+v shows struct field names. %#v prints Go syntax (great for debugging).

type Point struct{ X, Y int }
p := Point{1, 2}
fmt.Printf("%v\n", p)
fmt.Printf("%+v\n", p)
fmt.Printf("%#v\n", p)
Output
{1 2}
{X:1 Y:2}
main.Point{X:1, Y:2}

%T — the type of a value

var x any = 3.14
fmt.Printf("%T\n", x)
Output
float64

%d, %b, %o, %x, %X — integers in different bases

fmt.Printf("%d %b %o %x %X\n", 255, 255, 255, 255, 255)
Output
255 11111111 377 ff FF

%s, %q, %x — strings

%s is raw. %q adds Go-quoted escapes. %x encodes as hex.

s := "hi\tthere"
fmt.Printf("%s\n", s)
fmt.Printf("%q\n", s)
fmt.Printf("%x\n", s)
Output
hi	there
"hi\tthere"
68690974686572650

%f, %e, %g — floats

%f = decimal, %e = scientific, %g = whichever is shorter.

fmt.Printf("%f\n", 1234.5678)
fmt.Printf("%e\n", 1234.5678)
fmt.Printf("%g\n", 1234.5678)
Output
1234.567800
1.234568e+03
1234.5678

%t, %c, %U, %p — booleans, runes, Unicode, pointers

fmt.Printf("%t\n", true)
fmt.Printf("%c %U\n", 'G', 'G')
x := 42
fmt.Printf("%p\n", &x)
Output
true
G U+0047
0xc000012345

Width, precision, padding, flags

Between the % and the verb you can put: flags (+, -, #, 0, space), width, and .precision.

Width — minimum column width

Positive width right-aligns, negative left-aligns.

fmt.Printf("[%5d]\n", 42)   // right-aligned
fmt.Printf("[%-5d]\n", 42)  // left-aligned
fmt.Printf("[%05d]\n", 42)  // zero-padded
Output
[   42]
[42   ]
[00042]

Precision on floats and strings

fmt.Printf("%.2f\n", 3.14159)   // 2 digits after point
fmt.Printf("%8.2f\n", 3.14159)  // width 8, precision 2
fmt.Printf("%.3s\n", "hello")   // truncate string to 3
Output
3.14
    3.14
hel

%+d and % d — signed with leading sign or space

fmt.Printf("%+d %+d\n", 7, -7)
fmt.Printf("% d % d\n", 7, -7)
Output
+7 -7
 7 -7

Scan / Sscan / Fscan

Parsing back. Scan reads from stdin, Sscan from a string, Fscan from a Reader.

Sscanf — parse a formatted string

var name string
var age int
n, err := fmt.Sscanf("Ada 36", "%s %d", &name, &age)
fmt.Println(n, err, name, age)
Output
2 <nil> Ada 36

Sscan — whitespace-separated

var a, b, c int
fmt.Sscan("1 2 3", &a, &b, &c)
fmt.Println(a + b + c)
Output
6

Stringer interface

Any type with a String() string method formats itself for %s and %v.

Custom formatting via Stringer

type Celsius float64
func (c Celsius) String() string {
    return fmt.Sprintf("%.1f°C", float64(c))
}
fmt.Println(Celsius(22.5))
Output
22.5°C

Error vs Stringer — error wins for %v

If a type implements both error and Stringer, the error method is used.

var err error = fmt.Errorf("boom")
fmt.Printf("%v\n", err)  // "boom"
fmt.Printf("%s\n", err)  // "boom"
Output
boom
boom