Printf vs Println
Go provides different functions for printing output, each suited for different use cases.
Using Println
Println prints values separated by spaces and adds a newline at the end:
ops, ok, fail := 2350, 543, 433
fmt.Println("total:", ops, "- success:", ok, "/", fail)
// Output: total: 2350 - success: 543 / 433
This is simple but gives you limited control over formatting.
Using Printf
Printf gives you precise control over output formatting using format specifiers:
ops, ok, fail := 2350, 543, 433
fmt.Printf("total: %d - success: %d / %d\n", ops, ok, fail)
// Output: total: 2350 - success: 543 / 433
Printf does not add a newline automatically - you need to include \n explicitly.
Format specifiers are placeholders that tell Printf how to format each value. They start with % followed by a character indicating the format type.
| Specifier | Type | Description | Example |
|---|
%d | int | Decimal integer | fmt.Printf("%d", 42) → 42 |
%f | float | Decimal floating point | fmt.Printf("%f", 3.14) → 3.140000 |
%s | string | String | fmt.Printf("%s", "hello") → hello |
%t | bool | Boolean | fmt.Printf("%t", true) → true |
%v | any | Default format | fmt.Printf("%v", anything) |
%T | any | Type of value | fmt.Printf("%T", 42) → int |
%q | string | Quoted string | fmt.Printf("%q", "hi") → "hi" |
Printing Types with %T
Use %T to discover the type of a variable:
var (
speed int
heat float64
off bool
brand string
)
fmt.Printf("%T\n", speed) // int
fmt.Printf("%T\n", heat) // float64
fmt.Printf("%T\n", off) // bool
fmt.Printf("%T\n", brand) // string
This is incredibly useful for debugging and learning.
%v prints the value in a default format, working with any type:
fmt.Printf("%v\n", 42) // 42
fmt.Printf("%v\n", 3.14) // 3.14
fmt.Printf("%v\n", true) // true
fmt.Printf("%v\n", "hello") // hello
Use %v when you want a simple default representation of any value. Use specific format specifiers when you need precise control.
Escape Sequences
Escape sequences let you include special characters in strings.
Common Escape Sequences
// Newline
fmt.Println("hi\nhi")
// Output:
// hi
// hi
// Tab
fmt.Println("Name:\tJohn")
// Output: Name: John
// Backslash
fmt.Println("C:\\Users\\Documents")
// Output: C:\Users\Documents
// Double quote
fmt.Println("She said \"Hello\"")
// Output: She said "Hello"
Escape Sequence Reference
| Sequence | Meaning |
|---|
\n | Newline (line break) |
\t | Tab |
\\ | Backslash |
\" | Double quote |
\' | Single quote |
\r | Carriage return |
Use escape character
Start with backslash \
Add the special character
Follow with the character you want to escape
Include in your string
The escape sequence is interpreted when the string is printed
Example:
fmt.Println("Line 1\nLine 2\nLine 3")
// Output:
// Line 1
// Line 2
// Line 3
fmt.Println("hi\\n\"hi\"")
// Output: hi\n"hi"
Width and Precision
You can specify width and precision for better formatting:
// Integers with minimum width
fmt.Printf("%5d\n", 42) // 42 (padded to 5 characters)
// Floats with precision
fmt.Printf("%.2f\n", 3.14159) // 3.14 (2 decimal places)
fmt.Printf("%8.2f\n", 3.14159) // 3.14 (width 8, precision 2)
Padding and Alignment
// Right-aligned (default)
fmt.Printf("%5d\n", 42) // 42
// Left-aligned with -
fmt.Printf("%-5d\n", 42) // 42
// Zero-padding
fmt.Printf("%05d\n", 42) // 00042
// Minimum width
fmt.Printf("%10s\n", "hello") // hello
// Left-aligned string
fmt.Printf("%-10s\n", "hello") // hello
// Quoted strings
fmt.Printf("%q\n", "hello") // "hello"
Multiple Values
You can format multiple values in one Printf call:
name := "Alice"
age := 30
height := 5.7
fmt.Printf("%s is %d years old and %.1f feet tall\n", name, age, height)
// Output: Alice is 30 years old and 5.7 feet tall
The format specifiers are matched with arguments in order.
Make sure the number of format specifiers matches the number of arguments. Too few or too many arguments will cause runtime errors.
Sprintf works like Printf but returns a string instead of printing:
name := "Bob"
age := 25
message := fmt.Sprintf("%s is %d years old", name, age)
fmt.Println(message) // Bob is 25 years old
This is useful when you need to build formatted strings for later use.
Practical Examples
Printing Table Data
fmt.Printf("%-10s %5s %8s\n", "Name", "Age", "Salary")
fmt.Printf("%-10s %5d %8.2f\n", "Alice", 30, 75000.50)
fmt.Printf("%-10s %5d %8.2f\n", "Bob", 25, 65000.00)
// Output:
// Name Age Salary
// Alice 30 75000.50
// Bob 25 65000.00
Debug Output
var speed int = 100
var temp float64 = 98.6
var active bool = true
fmt.Printf("speed: %v (type: %T)\n", speed, speed)
fmt.Printf("temp: %v (type: %T)\n", temp, temp)
fmt.Printf("active: %v (type: %T)\n", active, active)
// Output:
// speed: 100 (type: int)
// temp: 98.6 (type: float64)
// active: true (type: bool)
Pretty Printing
fmt.Printf("User Information:\n")
fmt.Printf(" Name: %s\n", "John Doe")
fmt.Printf(" Age: %d\n", 30)
fmt.Printf(" Email: %s\n", "[email protected]")
fmt.Printf(" Active: %t\n", true)
// Output:
// User Information:
// Name: John Doe
// Age: 30
// Email: [email protected]
// Active: true
Best Practices
- Use specific format specifiers -
%d for integers, %f for floats, %s for strings
- Include \n when needed -
Printf doesn’t add newlines automatically
- Use %v for debugging - it works with any type
- Use %T to check types - helpful when learning or debugging
- Align output for readability - use width and padding for tabular data
When debugging, %#v provides Go syntax representation of a value, which can be very helpful for understanding complex data structures.
Common Patterns
Error messages with context
filename := "data.txt"
lineNum := 42
fmt.Printf("Error in %s at line %d\n", filename, lineNum)
Progress indicators
current := 75
total := 100
fmt.Printf("Progress: %d/%d (%.1f%%)\n", current, total, float64(current)/float64(total)*100)
// Output: Progress: 75/100 (75.0%)
timestamp := "2024-03-15 10:30:45"
level := "INFO"
message := "Server started"
fmt.Printf("[%s] %s: %s\n", timestamp, level, message)
// Output: [2024-03-15 10:30:45] INFO: Server started
Mastering Printf formatting gives you powerful control over program output. It’s essential for creating readable debug output, user-facing messages, and formatted reports.