I/O Operations in Go
Learn console input and output, formatted printing, and reading and writing files in Go with practical Docker-ready examples
Input and output are how a program talks to the outside world — the terminal, files, and other processes. Go handles I/O through a small set of well-designed packages built around simple interfaces (io.Reader and io.Writer) that compose cleanly across the standard library.
The fmt package covers formatted console I/O, bufio provides buffered reading and writing for efficiency, and the os package exposes files and the standard streams (os.Stdin, os.Stdout, os.Stderr). A defining feature of Go’s I/O is explicit error handling: functions that can fail return an error value that you are expected to check, rather than throwing exceptions.
In this tutorial you’ll go beyond the single fmt.Println from Hello World to learn the format verbs, read user input from the terminal, and write and read files — always with idiomatic Go error handling.
Formatted Output
Go’s fmt package offers several ways to print. Println adds spaces and a newline, Print does neither, and Printf uses format verbs (%s, %d, %f, and more) for precise control. Sprintf returns the formatted result as a string instead of printing it.
Create a file named formatted_output.go:
| |
Common verbs: %s (string), %d (integer), %f (float, with %.2f for precision), %t (boolean), %v (any value in its default format), and %T (the value’s type). Running formatted_output.go prints:
Hello, Ada
Age: 37
Ada is 37 years old
Pi rounded: 3.14
Hex: ff, Binary: 101
Welcome, Ada!
Reading Input from the Terminal
To read what a user types, wrap os.Stdin in a bufio.Scanner. Each call to Scan() reads one line, and Text() returns it (without the trailing newline). This is the idiomatic way to read line-based input in Go.
Create a file named read_input.go:
| |
Because this program reads from standard input, you supply the answers when you run it. Piping in Ada and 37 produces:
Enter your name: Enter your age: Hello, Ada! You are 37 years old.
The two prompts appear back-to-back because piped input is not echoed to the terminal the way interactive typing is. When run interactively, you would see each prompt, type a response, and press Enter.
Writing and Reading Files
File I/O showcases Go’s error-handling style: every operation that can fail returns an error alongside its result, and you check it before proceeding. The example below writes three lines to a file using a buffered writer, reads the whole file back at once with os.ReadFile, then reads it again line by line with a scanner.
Create a file named file_io.go:
| |
A few things to note:
os.Createopens a file for writing, creating it or truncating an existing one.bufio.NewWriterbuffers writes; callFlush()to ensure buffered data reaches the file before you close it.fmt.Fprintlnwrites to anyio.Writer(here the buffered writer) — the same formatting family asPrintln, redirected to a destination.defer f.Close()schedules the close to run whenmainreturns, a common Go idiom for cleanup.os.ReadFileis the simplest way to read an entire small file; the scanner approach suits large files you want to process one line at a time.
Running with Docker
The file_io.go example is fully self-contained — it creates its own file and reads it back — so it runs the same way every time.
| |
To try the interactive input example, pipe answers into standard input:
| |
Expected Output
Running file_io.go produces:
Wrote 3 lines to notes.txt
First line
Second line
Third line
Reading line by line:
1: First line
2: Second line
3: Third line
The notes.txt file is created in your working directory (mounted into the container via $(pwd)), so it persists after the container exits.
Key Concepts
io.Readerandio.Writerare the two interfaces at the heart of Go I/O — most I/O functions accept or return them, so components compose freely.fmtverbs (%s,%d,%.2f,%v,%T) give precise control over formatting;SprintfandFprintlnreuse the same formatting for strings and arbitrary writers.- Errors are values — I/O functions return an
erroryou check explicitly (if err != nil), rather than throwing exceptions. bufiobuffers I/O for efficiency:bufio.Scannerreads input line by line, andbufio.Writerbatches writes (remember toFlush()).os.Create,os.Open, andos.ReadFilecover the common file operations; pairOpen/Createwithdefer file.Close()to guarantee cleanup.- Standard streams
os.Stdin,os.Stdout, andos.Stderrare just*os.Filevalues you can read from or write to like any other file.
Comments
Loading comments...
Leave a Comment