Go by Example: Directories and Paths
Go 1.23
Learn to manipulate the filesystem with Go's `os` and `path/filepath` packages. This example covers creating directories, reading directory contents, checking file existence, and recursively walking directory trees.
Code
package main
import (
"fmt"
"os"
"path/filepath"
)
func check(e error) {
if e != nil {
panic(e)
}
}
func main() {
// Create a new directory
err := os.Mkdir("subdir", 0755)
check(err)
// Defer cleanup
defer os.RemoveAll("subdir")
// Create a helper function to create empty files
createEmptyFile := func(name string) {
d := []byte("")
check(os.WriteFile(name, d, 0644))
}
createEmptyFile("subdir/file1")
// Create hierarchy of directories
err = os.MkdirAll("subdir/parent/child", 0755)
check(err)
createEmptyFile("subdir/parent/file2")
createEmptyFile("subdir/parent/file3")
createEmptyFile("subdir/parent/child/file4")
// Read directory contents
c, err := os.ReadDir("subdir/parent")
check(err)
fmt.Println("Listing subdir/parent:")
for _, entry := range c {
fmt.Println(" ", entry.Name(), entry.IsDir())
}
// Change current working directory
err = os.Chdir("subdir/parent/child")
check(err)
// Get current directory
dir, err := os.Getwd()
check(err)
fmt.Println("CWD:", dir)
// Walk directory tree recursively
fmt.Println("Visiting subdir:")
err = filepath.Walk("../../", visit)
}
// visit function called for every file/dir visited
func visit(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
fmt.Println(" ", path, info.IsDir())
return nil
}Explanation
Go provides distinct packages for filesystem operations: os for interacting with the operating system (creating, deleting, stating files) and path/filepath for manipulating path strings in a cross-platform way.
Key directory operations include:
- Creating:
os.MkdirAll(path, perm)is usually preferred overMkdiras it creates parent directories as needed (likemkdir -p). - Reading: Use
os.ReadDir(introduced in Go 1.16). It returnsfs.DirEntryobjects which are more efficient than the olderos.FileInfobecause they avoid unnecessary system calls (stat) for file details. - Walking: Use
filepath.WalkDir(Go 1.16+) instead offilepath.Walk. It is significantly more performant for large directory trees because it streams directory entries and avoids stating every file unless requested.
Code Breakdown
17
Mkdir creates a new directory with the specified permissions (0755 = rwxr-xr-x).
32
MkdirAll creates a directory and all necessary parents. If the directory already exists, it does nothing (no error).
40
ReadDir reads the named directory and returns a list of directory entries sorted by filename.
59
filepath.Walk walks the file tree rooted at root, calling walkFn for each file or directory in the tree, including root.

