File I/O
Go's standard library provides layered file I/O: simple whole-file helpers, low-level os file handles, and the composable io.Reader/io.Writer interfaces.
Simple whole-file operations
For small files where the entire content fits comfortably in memory:
The permission bits 0644 grant the owner read+write and everyone else read-only.
Opening and creating files
os.Open returns an *os.File for reading. os.Create creates (or truncates) a file for writing:
Always defer f.Close() immediately after a successful open โ it fires even if the function returns early or panics.
For more control over open flags and permissions, use os.OpenFile:
Common flag combinations:
| Flags | Use case |
|---|---|
os.O_RDONLY | Read-only (default for os.Open) |
os.O_WRONLY | Write-only |
os.O_RDWR | Read and write |
os.O_CREATE | Create if it doesn't exist |
os.O_TRUNC | Truncate to zero (default for os.Create) |
os.O_APPEND | Append; every write goes to end of file |
Line-by-line reading with bufio.Scanner
bufio.Scanner is the idiomatic way to read line by line:
io.Writer โ the complement to io.Reader
Just as io.Reader is the interface for reading, io.Writer is the interface for writing:
*os.File, bytes.Buffer, strings.Builder, and many more implement io.Writer. Write to any of them uniformly:
Streaming with io.Copy
io.Copy reads from a Reader and writes to a Writer in chunks โ no need to load the whole file into memory:
Path manipulation with path/filepath
path/filepath handles OS-specific path separators correctly (forward slash on Unix, backslash on Windows):
Temp files
os.CreateTemp creates a uniquely-named file for scratch data:
Knowledge Check
What is the idiomatic way to ensure a file is closed after opening it?
Which os.OpenFile flag combination appends to an existing file without truncating it?
What does io.Copy do?