Working with the File System in Go: A Beginner's Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Working with the File System in Go: A Beginner's Guide



Go (Golang) is a modern compiled language known for its simplicity, performance, and built-in tools. One of the key tasks for any backend developer is interacting with the file system: reading configurations, writing logs, creating temporary files and directories. In this article, we will cover the basic operations with files and folders in Go, starting from the very basics. The material is designed for beginners, so each step will be accompanied by clear code examples.



Main Packages for Working with Files



The Go standard library has two main packages for working with the file system:

  • os — low-level work with files, folders, permissions, and processes.
  • io/ioutil (deprecated in Go 1.16, but still encountered) — convenient functions for reading/writing entire files.
  • io — interfaces for streaming input/output.
  • bufio — buffered reading/writing (useful for large files).


Starting from Go 1.16, it is recommended to use functions from the os package (os.ReadFile, os.WriteFile) instead of ioutil. We will rely on the modern approach.



Reading Files



The simplest way to read a small file entirely is to use os.ReadFile. It returns a byte slice and an error.



package main

import ( "fmt" "os")

func main() { // Reading the entire file data, err := os.ReadFile("example.txt") if err != nil { fmt.Println("Error reading file:", err) return } fmt.Println("File contents:") fmt.Println(string(data))}


If the file is large (e.g., a log file hundreds of megabytes in size), it is better to read it line by line or in blocks using bufio.Scanner:



package main

import ( "bufio" "fmt" "os")

func main() { file, err := os.Open("bigfile.log") if err != nil { fmt.Println("Error opening file:", err) return } defer file.Close() // always close the file

scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() fmt.Println(line) // process the line }

if err := scanner.Err(); err != nil { fmt.Println("Scanning error:", err) }}


Note the defer file.Close() — this ensures the file will be closed after the function completes, even if an error occurs.



Writing to Files



To write data to a file, use os.WriteFile (creates/overwrites the file) or os.Create + Write (for more flexible writing).



package main

import ( "fmt" "os")

func main() { // Simple string write to a file text := "Hello, world!Second line." err := os.WriteFile("output.txt", []byte(text), 0644) if err != nil { fmt.Println("Write error:", err) return } fmt.Println("File successfully written")}


The parameter 0644 is the Unix-style permission (owner can read/write, others can only read).



If you need to append data to the end of a file, use os.OpenFile with the os.O_APPEND flag:



package main

import ( "fmt" "os")

func main() { file, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { fmt.Println("Error opening file:", err) return } defer file.Close()

_, err = file.WriteString("New log entry") if err != nil { fmt.Println("Write error:", err) }}


Working with Directories

Blogs

Book Recommendations