How to use embed package

Use the `embed` package to compile static files directly into your Go binary at build time, eliminating the need for external file dependencies or runtime file system access.

Use the embed package to compile static files directly into your Go binary at build time, eliminating the need for external file dependencies or runtime file system access. You import the package, declare a variable with the //go:embed directive pointing to your files, and then access them via the Read() method or by casting to http.FileServer.

Here is a practical example of embedding a single file and reading its content:

package main

import (
	"embed"
	"fmt"
	"io"
)

//go:embed config.json
var ConfigFile embed.FS

func main() {
	data, err := ConfigFile.ReadFile("config.json")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(data))
}

For serving a directory of assets (like HTML, CSS, and JS) via an HTTP server, you can embed the entire directory and use http.FileServer:

package main

import (
	"embed"
	"net/http"
)

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

func main() {
	// fs.Sub creates a sub-filesystem rooted at "static"
	fs := http.FileServer(http.FS(http.Dir("static"))) 
	// Or for embed.FS specifically:
	// fs := http.FileServer(http.FS(StaticFiles))
	
	// Note: If you embed "static/*", the root is "static". 
	// To serve from root, use http.FS(StaticFiles) and access via /static/...
	// Or use http.FS(http.Dir("static")) if not embedding, but here we use embed:
	
	fs = http.FileServer(http.FS(StaticFiles))
	http.Handle("/", fs)
	http.ListenAndServe(":8080", nil)
}

Key patterns to remember:

  1. Wildcards: Use //go:embed static/* to include all files in a directory recursively.
  2. Patterns: You can use //go:embed *.html to match specific file types.
  3. Access: The embedded variable is an embed.FS which implements fs.FS. Use ReadFile() for single files or http.FS() to serve directories.
  4. Build Time: Files are read during compilation. If a file is missing or the pattern doesn't match, the build fails immediately.

This approach is ideal for configuration files, templates, and web assets where you want a single, self-contained executable.