The shapes experienced Go code keeps reaching for — how a constructor takes its options, how a service shuts down cleanly, when to give up on a slow call — and when the pattern is not worth it yet.
WHEN TO USE
SCOPE
USE FOR
Design a constructor with functional options instead of a long positional parameter list.
Decide whether a failure case should return an error or panic.
Add a timeout to every external call so a slow upstream can't hang a goroutine forever.
Stream a million-row transfer instead of loading it all into memory.
Choose an architecture style — clean, hexagonal, DDD, or flat — for a new service.
NOT FOR
Not for wiring a DI container or comparing DI libraries in depth.
Not for error wrapping, errors.Is/As matching, or structured-logging mechanics.
This is a saved copy of the skill's SKILL.md instructions. It may differ from the upstream file or the version you install.
Persona: You are a Go architect who values simplicity and explicitness. You apply patterns only when they solve a real problem — not to demonstrate sophistication — and you push back on premature abstraction.
Modes:
Design mode — creating new APIs, packages, or application structure: ask the developer about their architecture preference before proposing patterns; favor the smallest pattern that satisfies the requirement.
Review mode — auditing existing code for design issues: scan for init() abuse, unbounded resources, missing timeouts, and implicit global state; report findings before suggesting refactors.
Community default. A company skill that explicitly supersedes samber/cc-skills-golang@golang-design-patterns skill takes precedence.
Go Design Patterns & Idioms
Idiomatic Go patterns for production-ready code. For error handling details see the samber/cc-skills-golang@golang-error-handling skill; for context propagation see samber/cc-skills-golang@golang-context skill; for struct/interface design see samber/cc-skills-golang@golang-structs-interfaces skill.
Best Practices Summary
Constructors SHOULD use functional options — they scale better as APIs evolve (one function per option, no breaking changes)
Functional options MUST return an error if validation can fail — catch bad config at construction, not at runtime
Avoid init() — runs implicitly, cannot return errors, makes testing unpredictable. Use explicit constructors
Enums SHOULD start at 1 (or Unknown sentinel at 0) — Go's zero value silently passes as the first enum member
Error cases MUST be handled first with early return — keep happy path flat
Panic is for bugs, not expected errors — callers can handle returned errors; panics crash the process
defer Close() immediately after opening — later code changes can accidentally skip cleanup
runtime.AddCleanup over runtime.SetFinalizer — finalizers are unpredictable and can resurrect objects
Every external call SHOULD have a timeout — a slow upstream hangs your goroutine indefinitely
Limit everything (pool sizes, queue depths, buffers) — unbounded resources grow until they crash
Retry logic MUST check context cancellation between attempts
Use strings.Builder for concatenation in loops → see samber/cc-skills-golang@golang-code-style
string vs []byte: use []byte for mutation and I/O, string for display and keys — conversions allocate
Iterators (Go 1.23+): use for lazy evaluation — avoid loading everything into memory
Stream large transfers — loading millions of rows causes OOM; stream keeps memory constant
//go:embed for static assets — embeds at compile time, eliminates runtime file I/O errors
Use crypto/rand for keys/tokens — math/rand is predictable → see samber/cc-skills-golang@golang-security
Regexp MUST be compiled once at package level — compilation is O(n) and allocates
Compile-time interface checks: var _ Interface = (*Type)(nil)
A little recode > a big dependency — each dep adds attack surface and maintenance burden
Design for testability — accept interfaces, inject dependencies
Constructor Patterns: Functional Options vs Builder
Functional Options (Preferred)
type Server struct {
addr string
readTimeout time.Duration
writeTimeout time.Duration
maxConns int
}
type Option func(*Server)
func WithReadTimeout(d time.Duration) Option {
return func(s *Server) { s.readTimeout = d }
}
func WithWriteTimeout(d time.Duration) Option {
return func(s *Server) { s.writeTimeout = d }
}
func WithMaxConns(n int) Option {
return func(s *Server) { s.maxConns = n }
}
func NewServer(addr string, opts ...Option) *Server {
// Default options
s := &Server{
addr: addr,
readTimeout: 5 * time.Second,
writeTimeout: 10 * time.Second,
maxConns: 100,
}
for _, opt := range opts {
opt(s)
}
return s
}
// Usage
srv := NewServer(":8080",
WithReadTimeout(30*time.Second),
WithMaxConns(500),
)
Constructors SHOULD use functional options — they scale better with API evolution and require less code. Use builder pattern only if you need complex validation between configuration steps.
Constructors & Initialization
Avoid init() and Mutable Globals
init() runs implicitly, makes testing harder, and creates hidden dependencies:
Multiple init() functions run in declaration order, across files in filename alphabetical order — fragile
Cannot return errors — failures must panic or log.Fatal
Runs before main() and tests — side effects make tests unpredictable
// Bad — hidden global state
var db *sql.DB
func init() {
var err error
db, err = sql.Open("postgres", os.Getenv("DATABASE_URL"))
if err != nil {
log.Fatal(err)
}
}
// Good — explicit initialization, injectable
func NewUserRepository(db *sql.DB) *UserRepository {
return &UserRepository{db: db}
}
Enums: Start at 1
Zero values should represent invalid/unset state:
type Status int
const (
StatusUnknown Status = iota // 0 = invalid/unset
StatusActive // 1
StatusInactive // 2
StatusSuspended // 3
)
Compile Regexp Once
// Good — compiled once at package level
var emailRegex = regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
func ValidateEmail(email string) bool {
return emailRegex.MatchString(email)
}
Use //go:embed for Static Assets
import "embed"
//go:embed templates/*
var templateFS embed.FS
//go:embed version.txt
var version string
Compile-Time Interface Checks
→ See samber/cc-skills-golang@golang-structs-interfaces for the var _ Interface = (*Type)(nil) pattern.
Error Flow Patterns
Error cases MUST be handled first with early return — keep the happy path at minimal indentation. → See samber/cc-skills-golang@golang-code-style for the full pattern and examples.
When to Panic vs Return Error
Return error: network failures, file not found, invalid input — anything a caller can handle
Panic: nil pointer in a place that should be impossible, violated invariant, Must* constructors used at init time
.Close() / Flush() errors: read-only cleanup can often use defer f.Close(), but write/flush resources must report close or flush errors when durability matters
Data Handling
string vs []byte vs []rune
Type
Default for
Use when
string
Everything
Immutable, safe, UTF-8
[]byte
I/O
Writing to io.Writer, building strings, mutations
[]rune
Unicode ops
len() must mean characters, not bytes
Avoid repeated conversions — each one allocates. Stay in one type until you need the other.
Iterators & Streaming for Large Data
Use iterators (Go 1.23+) and streaming patterns to process large datasets without loading everything into memory. For large transfers between services (e.g., 1M rows DB to HTTP), stream to prevent OOM.
Retry logic MUST check ctx.Err() between attempts and use exponential/linear backoff via select on ctx.Done(). Long loops MUST check ctx.Err() periodically. → See samber/cc-skills-golang@golang-context skill.
Database Patterns
→ See samber/cc-skills-golang@golang-database skill for sqlx/pgx, transactions, nullable columns, connection pools, repository interfaces, testing.
Architecture
Ask the developer which architecture they prefer: clean architecture, hexagonal, DDD, or flat layout. Don't impose complex architecture on a small project.
Core principles regardless of architecture:
Keep domain pure — no framework dependencies in the domain layer
Fail fast — validate at boundaries, trust internal code
Make illegal states unrepresentable — use types to enforce invariants
Respect 12-factor app principles — → see samber/cc-skills-golang@golang-project-layout
Avoid repetitive code — but don't abstract prematurely
Minimize dependencies — a little recode > a big dependency
Design for testability — accept interfaces, inject dependencies, keep functions pure
Cross-References
→ See samber/cc-skills-golang@golang-data-structures skill for data structure selection, internals, and container/ packages
→ See samber/cc-skills-golang@golang-error-handling skill for error wrapping, sentinel errors, and the single handling rule
→ See samber/cc-skills-golang@golang-structs-interfaces skill for interface design and composition
→ See samber/cc-skills-golang@golang-concurrency skill for goroutine lifecycle and graceful shutdown
→ See samber/cc-skills-golang@golang-context skill for timeout and cancellation patterns
→ See samber/cc-skills-golang@golang-project-layout skill for architecture and directory structure
→ See samber/cc-skills-golang@golang-refactoring skill for safely staging a migration toward one of these patterns (options struct, DI, consumer-side interfaces) across an existing codebase
No requirements beyond installing this skill were found.
Listed as free
Connected services may require an account or charge fees.
Setup details
The README mentions source builds, cloning, containers, hosting, OAuth, service accounts, or cloud projects.
Run this outside your AI tool, using Node.js 22.20.0 or newer. Skills CLI 1.7.2 skips skill selection; prompts cancel installation without an interactive terminal. If choosing Project when asked about installation scope, open your project's folder before running this.
Install checklist
Check selected tools if a picker appears; Claude Code may be unchecked under Additional agents. ↑/↓ moves, Space toggles selections, Enter confirms.
Without a tool picker, check Installing to: for your intended tool. Stop if it names a different tool.
If asked, choose Symlink (Recommended) for shared files or Copy to all agents for separate copies; review the summary before confirming installation.
Install the find-skills skill? defaults to Yes, adding another skill for all projects. Choose No if you don't want that extra installation.
Skills CLI 1.7.2 sends install data to skills.sh by default, including the source, skill names, target tools and file details; GitHub sources are reported only when GitHub confirms the repository is public, while other remote sources can also be reported. Confirmed-public GitHub sources also trigger a security-audit request. Before installing, set the environment variable DO_NOT_TRACK=1 or DISABLE_TELEMETRY=1 to disable both.
After installing for Claude Code, open it in the installation project if you chose Project; Global makes the skill available across projects on this computer. Once Claude Code loads the skill, its description helps Claude decide when to use it.
If installation created a top-level skills folder that did not exist when your Claude Code session started, run /reload-skills in that session. Run it again after later changes in that folder.
Install the whole plugin
This route installs the Samber Golang Skills plugin package selected for your AI tool.
Add Samuel's marketplace, then install the plugin
Type both lines inside a Claude Code session, not at your shell prompt. The marketplace is a separate repository of Samuel Berthe's, samber/cc, which also lists his other plugins. The second line opens the details of cc-skills-golang, which carries this repository's 46 Go skills; pick one of the install options shown and Claude Code installs it.
01
/plugin marketplace add samber/cc
02
/plugin install cc-skills-golang@samber
Run it in your terminal. It copies the whole repository, with its 46 skills, into ~/.openclaw/skills/cc-skills-golang, OpenClaw's skills folder in your home folder. To install it for one OpenClaw workspace instead, Samuel gives ~/.openclaw/workspace/skills/cc-skills-golang as the folder.
Run it in your terminal, not inside Gemini CLI; installing from GitHub needs git on your computer. It installs the repository, with its 46 skills, as a Gemini CLI extension. To update it later, run gemini extensions update cc-skills-golang.
Run it in your terminal. It copies the whole repository, with its 46 skills, into ~/.cursor/skills/cc-skills-golang, Cursor's skills folder in your home folder.
Type it in an interactive GitHub Copilot CLI session, not at your shell prompt. It installs the repository straight from GitHub as a plugin, with its 46 skills and no marketplace to add first.
Golang benchmarking, profiling, and performance measurement. Use when writing, running, or comparing Go benchmarks, profiling hot paths with pprof, interpreting CPU/memory/trace profiles, analyzing results with benchstat, setting up CI benchmark regression detection, or investigating production performance with Prometheus runtime metrics. Also use when the developer needs deep analysis on a specific performance indicator - this skill provides the measurement methodology, while samber/cc-skills-golang@golang-performance provides the optimization patterns.Read full description
Golang CLI application development. Use when building, modifying, or reviewing a Go CLI tool — especially for command structure, flag handling, configuration layering, version embedding, exit codes, I/O patterns, signal handling, shell completion, argument validation, and CLI unit testing. Also triggers when code uses cobra, viper, or urfave/cli. For cobra-specific APIs → See samber/cc-skills-golang@golang-spf13-cobra skill; for viper configuration layering → See samber/cc-skills-golang@golang-spf13-viper skill.Read full description
Golang code style conventions — line length and breaking, variable declarations, control flow clarity, when comments help vs hurt. Use when writing or reviewing Go code, asking about style or clarity, or establishing project coding standards. Not for naming conventions (→ See samber/cc-skills-golang@golang-naming skill), linter configuration (→ See samber/cc-skills-golang@golang-lint skill), or doc comments (→ See samber/cc-skills-golang@golang-documentation skill).Read full description
Golang concurrency patterns. Use when writing or reviewing concurrent Go code involving goroutines, channels, select, locks, sync primitives, errgroup, singleflight, worker pools, or fan-out/fan-in pipelines. Also triggers when you detect goroutine leaks, race conditions, channel ownership issues, or need to choose between channels and mutexes.Read full description
Idiomatic context.Context usage in Golang — propagation through API boundaries, cancellation, timeouts and deadlines, request-scoped values, context.WithoutCancel for background work outliving requests. Apply when designing context propagation across layers, debugging leaked or unexpired contexts, choosing between context.Background/TODO/WithoutCancel, or storing values in context. Not for code that merely accepts ctx as first parameter.Read full description
CI/CD pipeline configuration using GitHub Actions for Golang projects — testing, linting, SAST, security scanning, code coverage, Dependabot, Renovate, GoReleaser, code review automation, and release pipelines. Use when setting up or improving Go project CI, configuring GitHub Actions workflows, adding linters or security scanners, automating dependency updates, or adding quality gates.Read full description