Go by Example: File Reading and Writing
Go 1.23
Learn File I/O operations in Go. This comprehensive example demonstrates reading files entirely, reading in chunks, and processing line-by-line using `bufio`, as well as creating and writing data to files using the `os` package.
Code
package main
import (
"bufio"
"fmt"
"os"
)
func check(e error) {
if e != nil {
panic(e)
}
}
func main() {
// --- Writing Files ---
// Write a string to a file
d1 := []byte("hello\ngo\n")
err := os.WriteFile("dat1.txt", d1, 0644)
check(err)
// Open file for more granular writing
f, err := os.Create("dat2.txt")
check(err)
defer f.Close()
// Write byte slice
d2 := []byte{115, 111, 109, 101, 10}
n2, err := f.Write(d2)
check(err)
fmt.Printf("wrote %d bytes\n", n2)
// Write string
n3, err := f.WriteString("writes\n")
check(err)
fmt.Printf("wrote %d bytes\n", n3)
// Flush writes to stable storage
f.Sync()
// --- Reading Files ---
// Read entire file into memory
dat, err := os.ReadFile("dat1.txt")
check(err)
fmt.Print(string(dat))
// Open file for granular reading
f2, err := os.Open("dat1.txt")
check(err)
defer f2.Close()
// Read first 5 bytes
b1 := make([]byte, 5)
n1, err := f2.Read(b1)
check(err)
fmt.Printf("%d bytes: %s\n", n1, string(b1[:n1]))
// Seek to a known location
o2, err := f2.Seek(6, 0)
check(err)
b2 := make([]byte, 2)
n2, err = f2.Read(b2)
check(err)
fmt.Printf("%d bytes @ %d: ", n2, o2)
fmt.Printf("%v\n", string(b2[:n2]))
// Buffered reading (efficient for many small reads)
r4 := bufio.NewReader(f2)
b4, err := r4.Peek(5)
check(err)
fmt.Printf("5 bytes: %s\n", string(b4))
}Explanation
Go provides comprehensive file I/O support in the os package. The approach you choose depends on the file size and your specific needs:
- Small Files: Use
os.ReadFileandos.WriteFile. These are convenient one-liners that handle opening, reading/writing the entire file, and closing it automatically. - Large Files & Streams: Use
os.Openwithbufio.NewScannerorbufio.Reader. This allows you to process data chunk-by-chunk or line-by-line without loading the entire file into memory, preventing OOM errors. - Fine Control: Use
os.Filemethods (Seek,ReadAt) when you need random access to specific parts of a file.
Under the hood, Go's I/O is built around the io.Reader and io.Writer interfaces. This powerful abstraction allows you to treat files, network connections, and in-memory buffers identically, making your code highly reusable and testable.
Code Breakdown
20
os.WriteFile is a helper that creates/truncates the file, writes the data, and closes it. 0644 is the file permission (rw-r--r--).
40
Sync() commits the current contents of the file to stable storage (flush). This ensures data is physically written to disk.
61
Seek sets the offset for the next Read or Write. The second argument 0 means relative to the origin of the file.
70
bufio.NewReader creates a buffered reader. Peek returns the next n bytes without advancing the reader position.

