uber-go-style

Uber Go style guide. Use when writing, reviewing, or modifying Go code to ensure it follows best practices for style, performance, error handling, concurrency, and naming conventions.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "uber-go-style" with this command: npx skills add ferhatelmas/goodies/ferhatelmas-goodies-uber-go-style

When writing or modifying Go code, follow these rules based on the Uber Go Style Guide.

Guidelines

Interfaces

  • Never use pointers to interfaces; pass interfaces as values
  • Verify interface compliance at compile time: var _ http.Handler = (*Handler)(nil)

Receivers

  • Value receivers can be called on pointers and values; pointer receivers only on pointers or addressable values

Mutexes

  • Zero-value sync.Mutex and sync.RWMutex are valid; don't use new(sync.Mutex)
  • Don't embed mutexes in structs; use a named field mu sync.Mutex

Slices and Maps at Boundaries

  • Copy slices and maps received as arguments if you store them (prevent caller mutation)
  • Copy slices and maps before returning them if they expose internal state

Defer

  • Use defer to clean up resources (files, locks). The overhead is negligible

Channels

  • Channel size should be one or unbuffered (zero). Any other size requires strong justification

Enums

  • Start enums at one with iota + 1 unless zero value is a meaningful default

Time

  • Use time.Time for instants, time.Duration for periods
  • Include unit in field names when time.Duration can't be used: IntervalMillis
  • Use RFC 3339 for timestamp strings

Errors

  • Use errors.New for static errors, fmt.Errorf for dynamic
  • Export error vars (ErrFoo) for caller matching via errors.Is; use custom types with Error suffix for errors.As
  • Wrap errors with %w (caller can match) or %v (opaque); avoid "failed to" prefixes: use "new store: %w" not "failed to create new store: %w"
  • Prefix exported error vars with Err, unexported with err
  • Handle errors once: either wrap and return, or log and degrade gracefully; never log AND return

Type Assertions

  • Always use the "comma ok" form: t, ok := i.(string)

Panics

  • Don't panic in production code; return errors instead
  • In tests, use t.Fatal not panic
  • Only acceptable for program initialization: template.Must(...)

Atomics

  • Prefer go.uber.org/atomic types (atomic.Bool, etc.) over raw sync/atomic for type safety

Mutable Globals

  • Avoid mutable globals; use dependency injection instead

Embedding Types

  • Don't embed types in public structs; delegate methods explicitly
  • Embedding leaks implementation details and inhibits type evolution

Built-In Names

  • Never shadow predeclared identifiers (error, string, len, cap, etc.)

init()

  • Avoid init(). Make it deterministic, no I/O, no global state mutation
  • Prefer var _defaultFoo = defaultFoo() or initialization in main()

Exit

  • Call os.Exit or log.Fatal only in main(); all other functions return errors
  • Prefer a single run() error function called from main() for testability

Field Tags

  • Always use field tags in marshaled structs: json:"price"

Goroutines

  • Don't fire-and-forget goroutines; every goroutine must have a way to stop and be waited on
  • Use sync.WaitGroup for multiple goroutines, a done channel for single ones
  • No goroutines in init(); expose objects with Shutdown()/Close() methods

Performance

  • Use strconv over fmt for primitive-to-string conversion
  • Don't repeatedly convert fixed strings to []byte; do it once
  • Specify capacity for slices: make([]T, 0, size) and maps: make(map[K]V, size)

Style

Formatting

  • Soft line length limit of 99 characters
  • Be consistent above all else

Declarations

  • Group similar declarations (const, var, type) but only group related items
  • Two import groups: standard library, then everything else (separated by blank line)

Naming

  • Package names: lowercase, no underscores, short, not plural, not "common/util/shared/lib"
  • Function names: MixedCaps; test functions may use underscores for grouping
  • Import aliases only when package name doesn't match last path element or on conflict
  • Prefix unexported globals with _ (except error vars which use err prefix)

Functions

  • Sort functions by rough call order; group by receiver
  • Exported functions first, after struct/const/var; NewXYZ() right after type definition
  • Utility functions at end of file

Control Flow

  • Reduce nesting: handle errors/special cases first, return early
  • Eliminate unnecessary else: use default value + conditional override
  • Reduce variable scope: if err := doThing(); err != nil

Variables

  • Use := for local variables with explicit values
  • Use var for zero-value declarations and empty slices
  • nil is a valid slice; return nil not []int{}; check emptiness with len(s) == 0

Parameters

  • Avoid naked bool parameters; use C-style comments or custom types for clarity

Strings

  • Use raw string literals to avoid escaping: `unknown error:"test"`

Structs

  • Use field names in struct initialization (enforced by go vet)
  • Omit zero-value fields unless they provide meaningful context
  • Use var s MyStruct for zero-value structs, not s := MyStruct{}
  • Use &T{Name: "bar"} not new(T) for struct references
  • Place embedded types at top of field list, separated by blank line

Maps

  • Use make(map[K]V) for empty/programmatic maps; use literals for fixed sets
  • Provide capacity hints when size is known

Printf

  • Declare format strings as const for go vet analysis
  • Name Printf-style functions with f suffix: Wrapf, not Wrap

Patterns

Test Tables

  • Use table-driven tests with subtests for repetitive test logic
  • Name the slice tests, each case tt, use give/want prefixes
  • Avoid complex conditional logic in table tests; split into separate test functions instead
  • For parallel table tests, ensure loop variables are scoped correctly

Functional Options

  • Use the functional options pattern for constructors with 3+ parameters
  • Implement with an Option interface and unexported options struct
  • Prefer concrete types over closures for debuggability and testability

Linting

  • Run at minimum: errcheck, goimports, revive, govet, staticcheck
  • Use golangci-lint as the lint runner
  • Lint consistently across the entire codebase

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

openclaw-version-monitor

监控 OpenClaw GitHub 版本更新,获取最新版本发布说明,翻译成中文, 并推送到 Telegram 和 Feishu。用于:(1) 定时检查版本更新 (2) 推送版本更新通知 (3) 生成中文版发布说明

Archived SourceRecently Updated
Coding

ask-claude

Delegate a task to Claude Code CLI and immediately report the result back in chat. Supports persistent sessions with full context memory. Safe execution: no data exfiltration, no external calls, file operations confined to workspace. Use when the user asks to run Claude, delegate a coding task, continue a previous Claude session, or any task benefiting from Claude Code's tools (file editing, code analysis, bash, etc.).

Archived SourceRecently Updated
Coding

ai-dating

This skill enables dating and matchmaking workflows. Use it when a user asks to make friends, find a partner, run matchmaking, or provide dating preferences/profile updates. The skill should execute `dating-cli` commands to complete profile setup, task creation/update, match checking, contact reveal, and review.

Archived SourceRecently Updated
Coding

clawhub-rate-limited-publisher

Queue and publish local skills to ClawHub with a strict 5-per-hour cap using the local clawhub CLI and host scheduler.

Archived SourceRecently Updated
uber-go-style | V50.AI