victorzhuk/skills

z-go-codegen-patterns

Use when authoring Go code generators, scaffold tools, AST manipulation, template-based codegen, golden-file tests, or YAML-driven generation pipelines.

Quelltext ansehen

Verwendung

  1. Installationsbefehl kopieren und das Quellpaket vor der Installation in der eigenen Agentenumgebung prüfen.
  2. Benötigte Werkzeuge, Zugangsdaten und Hosts im Original prüfen.
  3. Eingabe und gewünschtes Ergebnis beschreiben und die Ausgabe mit den Quellen abgleichen.
npx skills add https://github.com/victorzhuk/skills --skill z-go-codegen-patterns

Vor dem Start

  • Die Installation umfasst weder Modellabo noch API-Kontingent oder Dateizugriffsrechte.
  • Sterne und Installationen zeigen Aktivität, keine unabhängige Qualitäts- oder Sicherheitsprüfung.
Originales Skill-Dokument

Aus dem Quell-Repository gerendert; Überschriften, Beispiele, Code, Tabellen, Links und Bilder bleiben erhalten.

Go Code Generation Patterns

Code generators produce Go source files from templates, AST manipulation, or a combination. The key principle: manipulate Go as a structured program, not as text.

When to Use

  • Writing or editing a code generator or scaffold tool
  • Authoring Go templates (*.go.tmpl)
  • Designing a YAML-driven manifest or block schema
  • Adding AST injection to a generator pipeline
  • Writing golden-file tests for generated output
  • Debugging injection failures or template rendering errors

AST Over String Edit

Never build generated Go source with strings.Replace or template string concatenation — it's fragile and breaks on formatting changes:

go
// Bad — fragile, breaks on formatting changes
content = strings.Replace(content, "// INSERT FIELDS HERE", newField, 1)

// Good — parse, mutate, format
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, path, src, parser.ParseComments)
if err != nil {
    return fmt.Errorf("parse %s: %w", path, err)
}
if !astutil.AddNamedImport(fset, f, alias, importPath) {
    return fmt.Errorf("add import %q: already present or failed", importPath)
}
var buf bytes.Buffer
if err := format.Node(&buf, fset, f); err != nil {
    return fmt.Errorf("format %s: %w", path, err)
}

Default toolchain: stdlib go/parser + golang.org/x/tools/go/ast/astutil — astutil.AddNamedImport, astutil.Apply for cursor-based traversal. Reach for github.com/dave/dst (dstutil.Apply) only when the edit must preserve comments through the round-trip — go/ast + go/printer/format.Node drops them.

Regex on Go source is fine for read-only existence checks — it's writing new source by string edit that's fragile, not detecting whether something already exists:

go
func HasGoFunction(src []byte, name string) bool {
    pat := `func\s+(\([^)]*\)\s+)?` + regexp.QuoteMeta(name) + `\s*\(`
    return regexp.MustCompile(pat).Match(src)
}
Read references/codegen-patterns.md for the full injection pipeline design, virtual contract patterns, and common failure modes.

Template Context Design

Pass a well-typed struct to templates, not map[string]any:

go
type GenerationContext struct {
    ModuleName  string
    PackageName string
    Vars        map[string]string
}

// Add helper methods for logic that would be messy in the template
func (c GenerationContext) ImportPath(rel string) string {
    return path.Join(c.ModuleName, rel)
}

Keep templates free of business logic. Move decisions (if/else chains, string transforms) into helper methods on the context struct.

YAML Indent Discipline

YAML uses spaces, never tabs. A single tab causes a parse error:

yaml: found a tab character where an indentation space is expected

Rules:

  • 2-space indentation in all YAML templates.
  • Never use \t in any YAML literal.
  • Test YAML templates by parsing the output with yaml.Unmarshal — don't just assert strings.

Schema Validation Before Render

Validate the manifest or schema before executing templates:

go
if err := schema.Validate(block); err != nil {
    return fmt.Errorf("validate block %s: %w", block.ID, err)
}

Early validation produces readable errors. Template execution errors on invalid input are hard to trace back to a source.

Test Strategy

Use golden files for generated output:

go
var update = flag.Bool("update", false, "update golden files")

func TestGenerate_HTTPServer(t *testing.T) {
    got, err := generator.Render(ctx, httpServerBlock, testVars)
    require.NoError(t, err)

    golden := filepath.Join("testdata", "http_server.go.golden")
    if *update || os.Getenv("UPDATE_GOLDEN") == "1" {
        require.NoError(t, os.WriteFile(golden, got, 0o644))
    }
    want, err := os.ReadFile(golden)
    require.NoError(t, err)
    assert.Equal(t, string(want), string(got))
}

Regenerate goldens on intentional changes with the project's verified update flag/environment variable — these are custom test conventions, not built-in Go flags. Run the existing bounded wrapper. Never commit goldens that fail to compile — run go build ./... on generated output in CI.

Injection Pipeline

A safe pipeline order prevents partial writes:

  1. Register capabilities (extension points) and injections (what to insert).
  2. Validate every injection target exists — fail before writing any files.
  3. Sort injections by priority (lower = applied first).
  4. Group by target file.
  5. Parse each target file once.
  6. Apply typed injectors (import, field, code, struct).
  7. Write formatted Go only when the file was modified.

If any step fails, abandon the entire generation run — never leave a partially-injected file.

Quick Reference

PatternRule
AST manipulationgo/parser + astutil by default; dst only to preserve comments
Existence detectionRegex on raw source is fine for read-only checks
Template contextTyped struct with helpers, not map[string]any
YAML indentationSpaces only, 2-space indent, tested by parse
Schema validationBefore render, not after
Test strategyGolden files + -update flag or UPDATE_GOLDEN=1 env var
Injection pipelineParse once, apply all injectors, write only if modified

Checklist

  • [ ] No strings.Replace or string concatenation to write generated Go source
  • [ ] Regex on Go source, if used, is read-only detection, not a source edit
  • [ ] Template context is a typed struct, not map[string]any
  • [ ] YAML templates tested by parsing output (not just string matching)
  • [ ] Schema validated before template execution
  • [ ] Golden files exist for non-trivial generated output
  • [ ] Golden files compile in CI
  • [ ] Injections write only modified files

Related Skills

  • [[z-go-style]] — formatting, naming, structure of the generated code itself
  • [[z-go-testing]] — table-driven tests, golden file patterns, test helpers
  • [[z-go-errors]] — error wrapping at pipeline stage boundaries
aus demselben Repository

Weitere Skills

Alle Skills
victorzhuk
Community

z-accessibility

Audit and improve web accessibility following WCAG 2.2 guidelines. Use when asked to "improve accessibility", "a11y audit", "WCAG compliance", "screen reader support", "keyboard navigation", or "make accessible".

Installationen
1
GitHub Stars
0
Aktualisiert
22. Okt.
victorzhuk
Community

z-algo-core

DS/algorithm selection judgment for production code, not competitive tricks — hash map for membership/dedup, slice+sort beats a tree until proven, heap for top-k, two-pointer/sliding-window for scans, BFS/DFS/topo-sort for dependency shapes. Triggers on Big-O, hash map vs tree. Does not cover profiling/tuning; see [[z-go-performance]].

Installationen
1
GitHub Stars
0
Aktualisiert
22. Okt.
victorzhuk
Community

z-bdd

BDD acceptance contracts for humans and agents across UI, API, and CLI products. Use for Gherkin, Given-When-Then, E2E acceptance, or scenario evidence. Define repeatable scenarios with explicit assertions and required outcomes. Test selection belongs to [[z-testing-strategy]]. Go harness wiring belongs to [[z-go-bdd]].

Installationen
1
GitHub Stars
0
Aktualisiert
22. Okt.
victorzhuk
Community

z-codegraph

Use an existing CodeGraph integration for call graphs, impact analysis, affected tests, or route discovery. Discover installed tools and index freshness; follow host LSP precedence and verify current source. Do not initialize indexes without user authorization.

Installationen
1
GitHub Stars
0
Aktualisiert
22. Okt.