Skip to content
Back to skills

Go Declarations

ASecurity

Use when declaring or initializing Go variables, constants, structs,

  • 8 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 6, 2026
ai-agentsgobashsqlexpressgit

Works with

  • claude code

Security analysis

A100/100

Scanned September 6, 2026

npx -y skills add muratmirgun/gophers --skill go-declarations --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Go Declarations?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Go Declarations
[![Security: A β€” Skills Directory](https://www.skillsdirectory.com/api/skills/muratmirgun-go-declarations-gophers/badge)](https://www.skillsdirectory.com/skills/muratmirgun-go-declarations-gophers)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: go-declarations
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).
user-invocable: false
license: MIT
compatibility: Designed for Claude Code or similar AI coding agents. `any` requires
  Go 1.18+.
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*)
metadata:
  openclaw:
    emoji: πŸ“
    homepage: https://github.com/muratmirgun/gophers
    requires:
      bins:
      - go
    install: []
---

# Go Declarations and Initialization

Pick the simplest declaration form that expresses your intent: scope variables tightly, group related declarations, and let the zero value do its job.

## Core Rules

1. **`:=` for locals with values; `var` for intentional zero values or top-level declarations.**
2. **Group related declarations in parenthesized blocks.** Separate unrelated ones into distinct blocks.
3. **Start enums at `iota + 1`** so the zero value is "invalid/unset" β€” unless zero is genuinely meaningful.
4. **Initialize structs with field names.** Omit zero-value fields; let defaults speak.
5. **Use `any`, not `interface{}`,** in all new code.
6. **Never shadow builtins** (`len`, `cap`, `error`, `new`, `make`, `copy`, `any`, `nil`, ...).

## Decision: var vs :=

| Context | Use | Example |
|---|---|---|
| Package-level | `var` (always) | `var startTime = time.Now()` |
| Local with computed value | `:=` | `s := "foo"` |
| Local zero-value, intentional | `var` | `var filtered []int` |
| Declared type differs from RHS | `var T = expr` | `var e error = f()` |

> Read [references/scope-and-shadowing.md](../../../skills/go-declarations/references/scope-and-shadowing.md) when fighting subtle bugs caused by `:=` redeclaring an outer variable.

## Group Related Declarations

```go
// Bad
const a = 1
const b = 2

// Good
const (
    a = 1
    b = 2
)
```

Inside functions, group adjacent vars even if loosely related:

```go
var (
    caller  = c.name
    format  = "json"
    timeout = 5 * time.Second
)
```

## Constants and iota

Zero is the default; reserve it for "uninitialized" by starting enums at `iota + 1`:

```go
type Operation int

const (
    Add      Operation = iota + 1 // 1
    Subtract                      // 2
    Multiply                      // 3
)
```

Use plain `iota` only when the zero value is the sensible default (e.g., `LogToStdout = iota`).

> Read [references/iota-and-literals.md](../../../skills/go-declarations/references/iota-and-literals.md) for bitmask enums, `String()` methods, raw strings, and composite-literal formatting.

## Initializing Structs

- **Always use field names.** Positional struct literals break on field reordering and are caught by `go vet`.
- **Omit zero-value fields** β€” clarity beats explicit zeros.
- **`var u User`** for a zero-value struct (not `u := User{}`).
- **`&T{...}` over `new(T)`** when you want a pointer.

```go
u := User{Name: "Ada", Email: "ada@example.com"}
sptr := &Config{Timeout: 5 * time.Second}
var empty Buffer // zero value, ready to use
```

Test tables with ≀3 fields may use positional literals when the meaning is obvious.

## Initializing Maps

| Scenario | Use | Example |
|---|---|---|
| Empty, will be populated | `make(map[K]V)` | `m := make(map[string]int)` |
| Nil, lazily allocated | `var` | `var m map[string]int` |
| Known entries up front | Literal | `m := map[string]int{"a": 1}` |

`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)`.

## Raw String Literals

Use backticks to avoid escape gymnastics:

```go
// Bad
re := "^\\s*name:\\s*\"(.*)\""

// Good
re := `^\s*name:\s*"(.*)"`
```

Ideal for regex, SQL, JSON, and multi-line text.

## `any`, not `interface{}`

```go
// Old
func Print(v interface{}) { ... }

// New
func Print(v any) { ... }
```

`any` is an alias for `interface{}` since Go 1.18 β€” same type, less noise.

## Don't Shadow Builtins

The 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.

```go
// Bad β€” shadows the builtin error type
var error string

// Good
var errorMessage string
```

`go vet` catches the most common cases.

> Read [references/structs-and-tags.md](../../../skills/go-declarations/references/structs-and-tags.md) when designing struct fields that cross a serialization boundary (JSON, YAML, protobuf), embedding types, or formatting many-field literals.

## Anti-Patterns

| Anti-pattern | Why it hurts | Do this instead |
|---|---|---|
| `u := User{}` for a zero value | Misleads readers into expecting non-defaults | `var u User` |
| `new(T)` then assign fields | Two-step where one works | `&T{Field: v}` |
| Positional struct literals (>3 fields) | Silent breakage on field reordering | Use field names |
| `iota` starting at 0 for an enum | Zero value collides with a real case | `iota + 1` |
| `var m map[string]int` then `m[k] = v` | Panic on nil map write | `m := make(map[string]int)` |
| Hand-escaped JSON or regex strings | Hard to read, easy to mistype | Raw string literal |
| `interface{}` in new code | Verbose, outdated | `any` |

## Verification Checklist

- [ ] Top-level declarations use `var`/`const`; locals use `:=` unless zero-value is intended
- [ ] Related `const`/`var`/`type` are in grouped blocks
- [ ] Enums start at `iota + 1` (or the zero value is explicitly meaningful)
- [ ] Struct literals use field names; zero-value fields are omitted
- [ ] Maps that will be written to are constructed with `make`
- [ ] No builtins shadowed (`error`, `len`, `cap`, ...)
- [ ] `any` used instead of `interface{}`

## References

- [references/scope-and-shadowing.md](../../../skills/go-declarations/references/scope-and-shadowing.md) β€” variable scope, `:=` redeclaration rules, shadowing traps
- [references/iota-and-literals.md](../../../skills/go-declarations/references/iota-and-literals.md) β€” iota patterns, bitmasks, raw strings, composite literals
- [references/structs-and-tags.md](../../../skills/go-declarations/references/structs-and-tags.md) β€” struct initialization, field tags, embedding

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.