← GophersCONTENT HISTORY

Update to Gophers

Snapshot Sep 30, 2026 · 23:14 UTC · version 0.1.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Use when declaring or initializing Go variables, constants, structs, or maps. Covers var vs :=, grouped declaration blocks, iota enums starting at 1, struct/map/slice composite literals, raw string literals, `any` over `interface{}`, and avoiding shadowed builtins. Apply proactively to any new struct, const block, or top-level var, even if the user did not ask about declaration style. Does not cover identifier naming (see go-naming).",
  "included_files": [
    {
      "relative_path": "agents/openai.yaml",
      "size_in_bytes": 231
    },
    {
      "relative_path": "references/iota-and-literals.md",
      "size_in_bytes": 1838
    },
    {
      "relative_path": "references/scope-and-shadowing.md",
      "size_in_bytes": 2139
    },
    {
      "relative_path": "references/structs-and-tags.md",
      "size_in_bytes": 2238
    }
  ],
  "name": "go-declarations",
  "skill_md_contents": "---\nname: go-declarations\ndescription: \"Use when declaring or initializing Go variables, constants, structs, or maps. Covers var vs :=, grouped declaration blocks, iota enums starting at 1, struct/map/slice composite literals, raw string literals, `any` over `interface{}`, and avoiding shadowed builtins. Apply proactively to any new struct, const block, or top-level var, even if the user did not ask about declaration style. Does not cover identifier naming (see go-naming).\"\nlicense: MIT\ncompatibility: \"Designed for Claude Code or similar AI coding agents. `any` requires Go 1.18+.\"\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*)\n---\n\n# Go Declarations and Initialization\n\nPick the simplest declaration form that expresses your intent: scope variables tightly, group related declarations, and let the zero value do its job.\n\n## Core Rules\n\n1. **`:=` for locals with values; `var` for intentional zero values or top-level declarations.**\n2. **Group related declarations in parenthesized blocks.** Separate unrelated ones into distinct blocks.\n3. **Start enums at `iota + 1`** so the zero value is \"invalid/unset\" — unless zero is genuinely meaningful.\n4. **Initialize structs with field names.** Omit zero-value fields; let defaults speak.\n5. **Use `any`, not `interface{}`,** in all new code.\n6. **Never shadow builtins** (`len`, `cap`, `error`, `new`, `make`, `copy`, `any`, `nil`, ...).\n\n## Decision: var vs :=\n\n| Context | Use | Example |\n|---|---|---|\n| Package-level | `var` (always) | `var startTime = time.Now()` |\n| Local with computed value | `:=` | `s := \"foo\"` |\n| Local zero-value, intentional | `var` | `var filtered []int` |\n| Declared type differs from RHS | `var T = expr` | `var e error = f()` |\n\n> Read [references/scope-and-shadowing.md](references/scope-and-shadowing.md) when fighting subtle bugs caused by `:=` redeclaring an outer variable.\n\n## Group Related Declarations\n\n```go\n// Bad\nconst a = 1\nconst b = 2\n\n// Good\nconst (\n    a = 1\n    b = 2\n)\n```\n\nInside functions, group adjacent vars even if loosely related:\n\n```go\nvar (\n    caller  = c.name\n    format  = \"json\"\n    timeout = 5 * time.Second\n)\n```\n\n## Constants and iota\n\nZero is the default; reserve it for \"uninitialized\" by starting enums at `iota + 1`:\n\n```go\ntype Operation int\n\nconst (\n    Add      Operation = iota + 1 // 1\n    Subtract                      // 2\n    Multiply                      // 3\n)\n```\n\nUse plain `iota` only when the zero value is the sensible default (e.g., `LogToStdout = iota`).\n\n> Read [references/iota-and-literals.md](references/iota-and-literals.md) for bitmask enums, `String()` methods, raw strings, and composite-literal formatting.\n\n## Initializing Structs\n\n- **Always use field names.** Positional struct literals break on field reordering and are caught by `go vet`.\n- **Omit zero-value fields** — clarity beats explicit zeros.\n- **`var u User`** for a zero-value struct (not `u := User{}`).\n- **`&T{...}` over `new(T)`** when you want a pointer.\n\n```go\nu := User{Name: \"Ada\", Email: \"ada@example.com\"}\nsptr := &Config{Timeout: 5 * time.Second}\nvar empty Buffer // zero value, ready to use\n```\n\nTest tables with ≤3 fields may use positional literals when the meaning is obvious.\n\n## Initializing Maps\n\n| Scenario | Use | Example |\n|---|---|---|\n| Empty, will be populated | `make(map[K]V)` | `m := make(map[string]int)` |\n| Nil, lazily allocated | `var` | `var m map[string]int` |\n| Known entries up front | Literal | `m := map[string]int{\"a\": 1}` |\n\n`make` signals \"initialized but empty\" — different from a nil map (which panics on write). Provide a size hint when the count is known: `make(map[K]V, n)`.\n\n## Raw String Literals\n\nUse backticks to avoid escape gymnastics:\n\n```go\n// Bad\nre := \"^\\\\s*name:\\\\s*\\\"(.*)\\\"\"\n\n// Good\nre := `^\\s*name:\\s*\"(.*)\"`\n```\n\nIdeal for regex, SQL, JSON, and multi-line text.\n\n## `any`, not `interface{}`\n\n```go\n// Old\nfunc Print(v interface{}) { ... }\n\n// New\nfunc Print(v any) { ... }\n```\n\n`any` is an alias for `interface{}` since Go 1.18 — same type, less noise.\n\n## Don't Shadow Builtins\n\nThe predeclared identifiers (`error`, `string`, `len`, `cap`, `append`, `copy`, `new`, `make`, `close`, `delete`, `panic`, `recover`, `any`, `true`, `false`, `nil`, `iota`) are not reserved words — Go lets you shadow them. Don't.\n\n```go\n// Bad — shadows the builtin error type\nvar error string\n\n// Good\nvar errorMessage string\n```\n\n`go vet` catches the most common cases.\n\n> Read [references/structs-and-tags.md](references/structs-and-tags.md) when designing struct fields that cross a serialization boundary (JSON, YAML, protobuf), embedding types, or formatting many-field literals.\n\n## Anti-Patterns\n\n| Anti-pattern | Why it hurts | Do this instead |\n|---|---|---|\n| `u := User{}` for a zero value | Misleads readers into expecting non-defaults | `var u User` |\n| `new(T)` then assign fields | Two-step where one works | `&T{Field: v}` |\n| Positional struct literals (>3 fields) | Silent breakage on field reordering | Use field names |\n| `iota` starting at 0 for an enum | Zero value collides with a real case | `iota + 1` |\n| `var m map[string]int` then `m[k] = v` | Panic on nil map write | `m := make(map[string]int)` |\n| Hand-escaped JSON or regex strings | Hard to read, easy to mistype | Raw string literal |\n| `interface{}` in new code | Verbose, outdated | `any` |\n\n## Verification Checklist\n\n- [ ] Top-level declarations use `var`/`const`; locals use `:=` unless zero-value is intended\n- [ ] Related `const`/`var`/`type` are in grouped blocks\n- [ ] Enums start at `iota + 1` (or the zero value is explicitly meaningful)\n- [ ] Struct literals use field names; zero-value fields are omitted\n- [ ] Maps that will be written to are constructed with `make`\n- [ ] No builtins shadowed (`error`, `len`, `cap`, ...)\n- [ ] `any` used instead of `interface{}`\n\n## References\n\n- [references/scope-and-shadowing.md](references/scope-and-shadowing.md) — variable scope, `:=` redeclaration rules, shadowing traps\n- [references/iota-and-literals.md](references/iota-and-literals.md) — iota patterns, bitmasks, raw strings, composite literals\n- [references/structs-and-tags.md](references/structs-and-tags.md) — struct initialization, field tags, embedding\n"
}

SHA-256 of public snapshot: c62eb1b42db580f0288ca1e20bdb8b24ca8831bc26382ac23a85b6e4e10a8f81