How to Embed an Entire Directory with go

embed

You cannot embed an entire directory as a single blob using `//go:embed`, but you can embed all files within a directory as a `fs.FS` interface by using a wildcard pattern like `dir/*`.

You cannot embed an entire directory as a single blob using //go:embed, but you can embed all files within a directory as a fs.FS interface by using a wildcard pattern like dir/*. This allows you to access the directory structure and individual files at runtime using the standard io/fs package.

Here is a practical example where we embed a static directory containing HTML and CSS files:

package main

import (
	"embed"
	"fmt"
	"io/fs"
	"net/http"
)

//go:embed static/*
var staticFS embed.FS

func main() {
	// Serve the embedded directory directly
	http.Handle("/static/", http.FileServer(http.FS(staticFS)))
	
	// Or read a specific file
	content, err := staticFS.ReadFile("static/index.html")
	if err != nil {
		fmt.Println("Error reading file:", err)
		return
	}
	fmt.Printf("File size: %d bytes\n", len(content))
	
	fmt.Println("Server starting on :8080")
	http.ListenAndServe(":8080", nil)
}

If you need to iterate over the files or check if the directory exists, use fs.WalkDir on the embedded filesystem. Note that the path in ReadFile or WalkDir must match the pattern used in the directive (e.g., static/index.html, not just index.html):

func listFiles() {
	fs.WalkDir(staticFS, "static", func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		if !d.IsDir() {
			fmt.Println("Found file:", path)
		}
		return nil
	})
}

Key constraints to remember: the wildcard * only matches files in the immediate directory, not subdirectories recursively. If you need to include subdirectories, use static/** (Go 1.20+ supports this, though static/* is often sufficient for flat structures). Also, the embedded files are compiled into the binary, so changes to the source files require a rebuild of the Go application to take effect. This approach is ideal for serving static assets, configuration files, or templates without needing external file dependencies.