Listing Directories in Go: A Complete Guide with Code Examples

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

Listing Directories in Go: From Simple to Advanced

\n\n

Working with the file system is one of the fundamental tasks of any programming language. In Go, it is implemented so elegantly that even a routine operation like list directory in Go turns into an exciting adventure. If you've ever wondered, "How do I get a list of files in a folder in Go?" — you've come to the right place. Today, we'll cover all possible methods, from simple output to recursive traversal with filtering.

\n\n

Why is this topic so popular on Stack Overflow? Because Go offers several approaches at once, and choosing the right one is half the battle. We'll look at the classic os.ReadDir, the deprecated ioutil.ReadDir (though you can still find it in older projects), and the powerful filepath.Walk for recursive traversal. Let's go!

\n\n

1. Simple Listing: os.ReadDir

\n\n

Starting with Go 1.16, the os package introduced a new method ReadDir, which has become the de facto standard. It returns a slice of os.DirEntry objects — lightweight descriptions of files and folders. Here's how it looks:

\n\n
package main\n\nimport (\n    "fmt"\n    "os"\n    "log"\n)\n\nfunc main() {\n    // Read the contents of the current directory\n    entries, err := os.ReadDir(".")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    fmt.Println("Contents of the current folder:")\n    for _, entry := range entries {\n        fmt.Printf("- %s (is directory: %v)\\n", entry.Name(), entry.IsDir())\n    }\n}\n
\n\n

This code will output all files and folders in the current directory. Note: os.ReadDir does not read subfolders — only the top level. If you need to list directory in Go recursively, read on.

\n\n

2. ioutil.ReadDir: Old but Familiar

\n\n

Before Go 1.16, everyone used ioutil.ReadDir. It returns []os.FileInfo — a heavier structure with full file information (size, permissions, modification time). Although the method is marked as deprecated, you can still find it in legacy code:

\n\n
package main\n\nimport (\n    "fmt"\n    "io/ioutil"\n    "log"\n)\n\nfunc main() {\n    files, err := ioutil.ReadDir("./mydir")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    fmt.Println("Files in mydir (old way):")\n    for _, file := range files {\n        fmt.Printf("Name: %s, Size: %d bytes\\n", file.Name(), file.Size())\n    }\n}\n
\n\n

The main difference: ioutil.ReadDir sorts the result by file name (like ls), while os.ReadDir does not. If order matters, use sort.Slice or manual sorting.

\n\n

3. Recursive Traversal with filepath.Walk

\n\n

When you need to go through all subfolders, filepath.Walk comes to the rescue. This function traverses the directory tree, calling a callback for each found item. Perfect for backups, file searches, or analyzing project structure:

\n\n
package main\n\nimport (\n    "fmt"\n    "os"\n    "path/filepath"\n)\n\nfunc main() {\n    root := "./myproject"\n    err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {\n        if err != nil {\n            return err\n        }\n        fmt.Printf("Found: %s (size: %d)\\n", path, info.Size())\n        return nil\n    })\n    if err != nil {\n        fmt.Println("Traversal error:", err)\n    }\n}\n
\n\n

An important nuance: filepath.Walk follows symlinks and can enter an infinite loop if there are cyclic references. For production, use filepath.WalkDir (Go 1.16+) — it is lighter and safer.

\n\n

4. Filtering: Only .go Files or Only Folders

\n\n

Often you need to get not everything, but only specific file types. Let's implement filtering using strings.HasSuffix and the IsDir() check.

Blogs

Book Recommendations