Input & Output
Learn to print formatted output with fmt.Println and fmt.Printf, and read user input with fmt.Scan and bufio.Scanner.
Introduction
Nearly every program needs to display information and, often, read input from a user. Go's standard library makes both straightforward through the `fmt` package for output and formatted printing, and `bufio` for more flexible input reading.
Printing with fmt.Println and fmt.Print
`fmt.Println` prints its arguments separated by spaces, followed by a newline. `fmt.Print` is similar but adds no automatic newline and only inserts spaces between operands when neither is a string.
package main
import "fmt"
func main() { fmt.Println("Go", "is", "fun") // adds spaces + newline automatically fmt.Print("No newline here") fmt.Print(" — continues on the same line.\n")}Click Run to see what this code prints.
Formatted Output with fmt.Printf
`fmt.Printf` gives you precise control over output formatting using a format string with placeholder "verbs" (like `%s`, `%d`) that get substituted with the arguments that follow.
package main
import "fmt"
func main() { name := "Alice" age := 30 gpa := 3.87
fmt.Printf("Name: %s, Age: %d, GPA: %.2f\n", name, age, gpa)}Click Run to see what this code prints.
Common Printf Verbs
| Verb | Meaning |
|---|---|
| %s | String |
| %d | Base-10 integer |
| %f | Floating-point number (use %.2f to control decimal places) |
| %t | Boolean (true/false) |
| %v | Default format for any value — great for debugging |
| %T | The type of a value |
| %q | A double-quoted string, safely escaped |
package main
import "fmt"
func main() { value := 42 fmt.Printf("%v is of type %T\n", value, value) fmt.Printf("%q\n", "quoted text")}Click Run to see what this code prints.
Building Strings with fmt.Sprintf
`fmt.Sprintf` works exactly like `fmt.Printf`, but instead of printing to the screen it returns the formatted result as a string — extremely useful for building messages, log lines, or error text.
package main
import "fmt"
func main() { name := "Bob" message := fmt.Sprintf("Welcome back, %s!", name) fmt.Println(message)}Click Run to see what this code prints.
Reading Input with fmt.Scan
`fmt.Scan` reads space-separated input values from standard input into the variables you pass by pointer (using `&`). It's simple, but stops reading at whitespace — so it can't capture a full line containing spaces.
package main
import "fmt"
func main() { var name string var age int
fmt.Print("Enter your name and age: ") fmt.Scan(&name, &age)
fmt.Printf("Hello %s, you are %d years old.\n", name, age)}Click Run to see what this code prints.
Reading Full Lines with bufio.Scanner
When you need to read an entire line, including spaces (like a full name or sentence), use `bufio.NewScanner` reading from `os.Stdin`.
package main
import ( "bufio" "fmt" "os")
func main() { scanner := bufio.NewScanner(os.Stdin)
fmt.Print("Enter a full sentence: ") scanner.Scan() line := scanner.Text()
fmt.Println("You typed:", line)}Click Run to see what this code prints.
Common Mistakes
- Forgetting the `&` when passing variables to fmt.Scan — it needs a pointer to write the value into.
- Using fmt.Scan to read a full line of text with spaces — it stops at the first whitespace character.
- Forgetting `\n` in fmt.Printf format strings, resulting in output that runs together on one line.
- Ignoring the error value that fmt.Scan and bufio.Scanner methods can return, especially in production code.
Best Practices
- Use fmt.Println for quick, simple output and fmt.Printf when you need precise formatting.
- Use bufio.Scanner whenever you need to read a full line, including sentences with spaces.
- Use %v for debugging unknown or complex values, and more specific verbs (%d, %s) for polished output.
- Prefer fmt.Sprintf over string concatenation when building formatted messages with multiple values.
Frequently Asked Questions
fmt.Println always adds a trailing newline and spaces between all arguments. fmt.Print adds no newline and only inserts spaces between two operands when neither one is a string.
fmt.Scan needs to write the value it reads back into your variable, which requires a pointer (memory address) to that variable — that's what the & operator provides.
Call scanner.Scan() repeatedly, typically inside a for loop, reading one line into scanner.Text() on each iteration until Scan() returns false (end of input).
Key Takeaways
- fmt.Println/Print handle simple output; fmt.Printf gives precise, verb-based formatting.
- Common verbs include %s (string), %d (integer), %f (float), %v (default format), and %T (type).
- fmt.Sprintf returns a formatted string instead of printing it.
- fmt.Scan reads space-separated values; bufio.Scanner reads full lines including spaces.
Summary
You can now print cleanly formatted output and read input from users in multiple ways. Next, you'll learn how to make decisions in your programs using if/else conditional statements.