Claude Agent Skill · by Samber

Golang Code Style

Install Golang Code Style skill for Claude Code from samber/cc-skills-golang.

Install
Terminal · npx
$npx skills add https://github.com/vercel-labs/agent-skills --skill vercel-react-best-practices
Works with Paperclip

How Golang Code Style fits into a Paperclip company.

Golang Code Style drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md235 lines
Expand
---name: golang-code-styledescription: "Golang code style, formatting and conventions. Use when writing code, reviewing style, configuring linters, writing comments, or establishing project standards."user-invocable: truelicense: MITcompatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang.metadata:  author: samber  version: "1.1.1"  openclaw:    emoji: "🎨"    homepage: https://github.com/samber/cc-skills-golang    requires:      bins:        - go    install: []allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent--- > **Community default.** A company skill that explicitly supersedes `samber/cc-skills-golang@golang-code-style` skill takes precedence. # Go Code Style Style rules that require human judgment — linters handle formatting, this skill handles clarity. For naming see `samber/cc-skills-golang@golang-naming` skill; for design patterns see `samber/cc-skills-golang@golang-design-patterns` skill; for struct/interface design see `samber/cc-skills-golang@golang-structs-interfaces` skill. > "Clear is better than clever." — Go Proverbs When ignoring a rule, add a comment to the code. ## Line Length & Breaking No rigid line limit, but lines beyond ~120 characters MUST be broken. Break at **semantic boundaries**, not arbitrary column counts. Function calls with 4+ arguments MUST use one argument per line — even when the prompt asks for single-line code: ```go// Good — each argument on its own line, closing paren separatemux.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {    handleUsers(        w,        r,        serviceName,        cfg,        logger,        authMiddleware,    )})``` When a function signature is too long, the real fix is often **fewer parameters** (use an options struct) rather than better line wrapping. For multi-line signatures, put each parameter on its own line. ## Variable Declarations SHOULD use `:=` for non-zero values, `var` for zero-value initialization. The form signals intent: `var` means "this starts at zero." ```govar count int              // zero value, set latername := "default"          // non-zero, := is appropriatevar buf bytes.Buffer       // zero value is ready to use``` ### Slice & Map Initialization Slices and maps MUST be initialized explicitly, never nil. Nil maps panic on write; nil slices serialize to `null` in JSON (vs `[]` for empty slices), surprising API consumers. ```gousers := []User{}                       // always initializedm := map[string]int{}                   // always initializedusers := make([]User, 0, len(ids))      // preallocate when capacity is knownm := make(map[string]int, len(items))   // preallocate when size is known``` Do not preallocate speculatively — `make([]T, 0, 1000)` wastes memory when the common case is 10 items. ### Composite Literals Composite literals MUST use field names — positional fields break when the type adds or reorders fields: ```gosrv := &http.Server{    Addr:         ":8080",    ReadTimeout:  5 * time.Second,    WriteTimeout: 10 * time.Second,}``` ## Control Flow ### Reduce Nesting Errors and edge cases MUST be handled first (early return). Keep the happy path at minimal indentation: ```gofunc process(data []byte) (*Result, error) {    if len(data) == 0 {        return nil, errors.New("empty data")    }     parsed, err := parse(data)    if err != nil {        return nil, fmt.Errorf("parsing: %w", err)    }     return transform(parsed), nil}``` ### Eliminate Unnecessary `else` When the `if` body ends with `return`/`break`/`continue`, the `else` MUST be dropped. Use default-then-override for simple assignments — assign a default, then override with independent conditions or a `switch`: ```go// Good — default-then-override with switch (cleanest for mutually exclusive overrides)level := slog.LevelInfoswitch {case debug:    level = slog.LevelDebugcase verbose:    level = slog.LevelWarn} // Bad — else-if chain hides that there's a defaultif debug {    level = slog.LevelDebug} else if verbose {    level = slog.LevelWarn} else {    level = slog.LevelInfo}``` ### Complex Conditions & Init Scope When an `if` condition has 3+ operands, MUST extract into named booleans — a wall of `||` is unreadable and hides business logic. Keep expensive checks inline for short-circuit benefit. [Details](./references/details.md) ```go// Good — named booleans make intent clearisAdmin := user.Role == RoleAdminisOwner := resource.OwnerID == user.IDisPublicVerified := resource.IsPublic && user.IsVerifiedif isAdmin || isOwner || isPublicVerified || permissions.Contains(PermOverride) {    allow()}``` Scope variables to `if` blocks when only needed for the check: ```goif err := validate(input); err != nil {    return err}``` ### Switch Over If-Else Chains When comparing the same variable multiple times, prefer `switch`: ```goswitch status {case StatusActive:    activate()case StatusInactive:    deactivate()default:    panic(fmt.Sprintf("unexpected status: %d", status))}``` ## Function Design - Functions SHOULD be **short and focused** — one function, one job.- Functions SHOULD have **≤4 parameters**. Beyond that, use an options struct (see `samber/cc-skills-golang@golang-design-patterns` skill).- **Parameter order**: `context.Context` first, then inputs, then output destinations.- Naked returns help in very short functions (1-3 lines) where return values are obvious, but become confusing when readers must scroll to find what's returned — name returns explicitly in longer functions. ```gofunc FetchUser(ctx context.Context, id string) (*User, error)func SendEmail(ctx context.Context, msg EmailMessage) error  // grouped into struct``` ### Prefer `range` for Iteration SHOULD use `range` over index-based loops. Use `range n` (Go 1.22+) for simple counting. ```gofor _, user := range users {    process(user)}``` ## Value vs Pointer Arguments Pass small types (`string`, `int`, `bool`, `time.Time`) by value. Use pointers when mutating, for large structs (~128+ bytes), or when nil is meaningful. [Details](./references/details.md) ## Code Organization Within Files - **Group related declarations**: type, constructor, methods together- **Order**: package doc, imports, constants, types, constructors, methods, helpers- **One primary type per file** when it has significant methods- **Blank imports** (`_ "pkg"`) register side effects (init functions). Restricting them to `main` and test packages makes side effects visible at the application root, not hidden in library code- **Dot imports** pollute the namespace and make it impossible to tell where a name comes from — never use in library code- **Unexport aggressively** — you can always export later; unexporting is a breaking change ## String Handling Use `strconv` for simple conversions (faster), `fmt.Sprintf` for complex formatting. Use `%q` in error messages to make string boundaries visible. Use `strings.Builder` for loops, `+` for simple concatenation. ## Type Conversions Prefer explicit, narrow conversions. Use generics over `any` when a concrete type will do: ```gofunc Contains[T comparable](slice []T, target T) bool  // not []any``` ## Philosophy - **"A little copying is better than a little dependency"**- **Use `slices` and `maps` standard packages**; for filter/group-by/chunk, use `github.com/samber/lo`- **"Reflection is never clear"** — avoid `reflect` unless necessary- **Don't abstract prematurely** — extract when the pattern is stable- **Minimize public surface** — every exported name is a commitment ## Parallelizing Code Style Reviews When reviewing code style across a large codebase, use up to 5 parallel sub-agents (via the Agent tool), each targeting an independent style concern (e.g. control flow, function design, variable declarations, string handling, code organization). ## Enforce with Linters Many rules are enforced automatically: `gofmt`, `gofumpt`, `goimports`, `gocritic`, `revive`, `wsl_v5`. → See the `samber/cc-skills-golang@golang-linter` skill. ## Cross-References - → See the `samber/cc-skills-golang@golang-naming` skill for identifier naming conventions- → See the `samber/cc-skills-golang@golang-structs-interfaces` skill for pointer vs value receivers, interface design- → See the `samber/cc-skills-golang@golang-design-patterns` skill for functional options, builders, constructors- → See the `samber/cc-skills-golang@golang-linter` skill for automated formatting enforcement