Go cookbook · Beginner
Embed static files and templates in the binary
Deployments break because templates or assets aren't copied next to the binary.
Approach
Use //go:embed to compile files into the binary, serve them with http.FileServerFS, and parse templates from
the embedded filesystem.
Solution
package main
import (
"embed"
"html/template"
"io/fs"
"log"
"net/http"
)
//go:embed static templates
var content embed.FS
func main() {
static, err := fs.Sub(content, "static")
if err != nil {
log.Fatal(err)
}
pages := template.Must(template.ParseFS(content, "templates/*.html"))
mux := http.NewServeMux()
mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServerFS(static)))
mux.HandleFunc("GET /{$}", func(w http.ResponseWriter, r *http.Request) {
if err := pages.ExecuteTemplate(w, "index.html", map[string]string{"Title": "Shop"}); err != nil {
http.Error(w, "template error", http.StatusInternalServerError)
}
})
log.Fatal(http.ListenAndServe(":8080", mux))
}
Pitfalls
- Embedding huge assets that bloat the binary; serve them from a CDN.
- Using
text/templatefor HTML, which doesn't escape output (XSS). - Forgetting that
//go:embedpaths are relative to the package directory and can't use...
Variations
- Set cache headers for fingerprinted assets (
Cache-Control: public, max-age=31536000, immutable). - In development, switch to
os.DirFS("static")to see changes without rebuilding.
Further reading: embed package
Reference: https://pkg.go.dev/embed
More Go recipes
- Benchmark code with testing.B.Loop
- Build a small, secure container image for a Go service
- Decode and validate JSON request bodies safely
- Load and validate configuration from environment variables
- Log structured JSON with slog and redact secrets
- Process jobs concurrently with a bounded worker pool
- Profile a running service with pprof
- Rate limit requests per client