Code Generation and Embedding

Updated

July 30, 2026

Overview

go generate runs commands to generate code, and //go:embed embeds files into binaries.

go generate

//go:generate stringer -type=Status

type Status int

const (
    Pending Status = iota
    Approved
    Rejected
)
go generate ./...

Common Generators

  • stringer - String methods for enums
  • mockgen - Mock interfaces for testing
  • protoc - Protocol buffer code

Embedding Files

import "embed"

//go:embed config.json
var configData []byte

//go:embed templates/*
var templates embed.FS

//go:embed static
var staticFiles embed.FS

Reading Embedded Files

//go:embed data.txt
var data string  // As string

//go:embed data.bin
var data []byte  // As bytes

//go:embed files/*
var fs embed.FS  // As filesystem

content, _ := fs.ReadFile("files/config.json")

HTTP File Server

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

func main() {
    fs := http.FileServer(http.FS(static))
    http.Handle("/static/", fs)
    http.ListenAndServe(":8080", nil)
}

Templates

//go:embed templates/*.html
var templates embed.FS

tmpl := template.Must(template.ParseFS(templates, "templates/*.html"))

Summary

Directive Purpose
//go:generate cmd Run code generator
//go:embed file Embed as string/bytes
//go:embed dir/* Embed as filesystem

Worked example

Generate a tiny constants file at runtime (stand-in for go generate output), then use it.

Save as main.go. Then:

go mod init example
go run .
package main

import (
    "fmt"
    "strings"
)

func generateVersionGo(version string) string {
    return fmt.Sprintf("// Code generated by demo; DO NOT EDIT.\npackage main\n\nconst GeneratedVersion = %q\n", version)
}

func main() {
    src := generateVersionGo("1.2.3")
    // Real workflows write this via //go:generate (stringer, sqlc, mockgen, …).
    fmt.Println(strings.TrimSpace(src))
    fmt.Println("lines:", strings.Count(src, "\n"))
}

Expected output:

// Code generated by demo; DO NOT EDIT.
package main

const GeneratedVersion = "1.2.3"
lines: 4

More examples

//go:embed string + FS in one program (needs a local file).

printf 'hi' > note.txt
package main

import (
    "embed"
    "fmt"
)

//go:embed note.txt
var note string

//go:embed note.txt
var fs embed.FS

func main() {
    fmt.Println("string:", note)
    b, _ := fs.ReadFile("note.txt")
    fmt.Println("fs:", string(b))
}

Expected output:

string: hi
fs: hi

Runnable example

Save as main.go and create a sibling hello.txt with the text embedded hello. Then:

go mod init example
printf 'embedded hello' > hello.txt
go run .
package main

import (
    "embed"
    "fmt"
    "io/fs"
    "strings"
)

//go:embed hello.txt
var hello string

//go:embed hello.txt
var helloBytes []byte

//go:embed hello.txt
var content embed.FS

// version is normally produced by go:generate; pure-Go fallback for this demo.
var version = "dev"

func main() {
    fmt.Println("embed string:", hello)
    fmt.Println("embed bytes:", string(helloBytes))

    b, err := content.ReadFile("hello.txt")
    if err != nil {
        panic(err)
    }
    fmt.Println("embed FS:", string(b))

    // Walk the embedded FS (handy for static assets)
    _ = fs.WalkDir(content, ".", func(path string, d fs.DirEntry, err error) error {
        if err != nil || d.IsDir() {
            return err
        }
        fmt.Println("walk:", path)
        return nil
    })

    // Stand-in for generated code: a tiny template expansion
    generated := strings.ReplaceAll(
        "// Code generated by demo; DO NOT EDIT.\nconst Version = \"{{V}}\"\n",
        "{{V}}",
        version,
    )
    fmt.Println(strings.TrimSpace(generated))
}

Expected output:

embed string: embedded hello
embed bytes: embedded hello
embed FS: embedded hello
walk: hello.txt
// Code generated by demo; DO NOT EDIT.
const Version = "dev"

What to notice: //go:embed paths are relative to the source file and bake content into the binary—no runtime file needed after build. Real go generate tools (stringer, sqlc, mockgen) write Go you commit or produce in CI; keep generators deterministic.

Try next: Embed a static/* directory and serve it with http.FileServer(http.FS(static)) via httptest. Add a //go:generate echo package main > zzz_gen.go and run go generate.