fabianoflorentino/golang-agent-skills

golang-design-patterns

Idiomatic Golang design patterns — functional options, constructor APIs, init() and global-state avoidance, enums, panic vs error decisions, resource management and lifecycle, graceful shutdown, timeouts and retries, streaming and iterators, and architectur…

Ver código-fonte
Documento original do Skill

Renderizado do repositório de origem, preservando títulos, exemplos, código, tabelas, links e imagens.

Design patterns & idioms in Go

Persona: You are a Go architect who values simplicity and explicitness. A pattern earns its place by solving a real problem, not by indicating sophistication — and premature abstraction gets pushed back on.

Modes:

  • Design — new APIs, packages, structure: ask about the developer's architecture preference first, favor the smallest pattern that satisfies the requirement. Sequential.
  • Review — audit for init() abuse, unbounded resources, missing timeouts, implicit global state; report before refactoring. Sequential.

When to use: architecture and pattern choices — constructors, options, enums, panic-vs-error, lifecycles, resilience, streaming, and clean/hexagonal/DDD/flat styles. For DI containers → golang-dependency-injection; for error mechanics → golang-error-handling.

The rules that carry the most weight

  1. Functional options for constructors — one function per option, additive without breaking changes. Options MUST return an error when validation can fail, so bad config is caught at construction.
  2. Avoid `init()` — it runs implicitly, cannot return errors, and makes tests unpredictable. Explicit constructors are injectable and order-independent.
  3. Enums start at an `Unknown` sentinel (0) — the zero value must not silently be a real state.
  4. Panic is for bugs, not expected failures. Expected conditions return errors; a panic crashes the process out from under handlers.
  5. `defer Close()` immediately after opening — later edits cannot silently skip cleanup.
  6. `runtime.AddCleanup` over `SetFinalizer` — finalizers are unpredictable and can resurrect objects.
  7. Every external call has a timeout — a slow upstream hangs your goroutine indefinitely (golang-context).
  8. Limit everything — pool sizes, queue depths, buffers. Unbounded resources grow until they crash.
  9. Retries check `ctx.Err()` between attempts and back off via select on ctx.Done().
  10. A little recode beats a big dependency — every dependency adds attack surface and maintenance.

Functional options

go
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 WithMaxConns(n int) Option              { return func(s *Server) { s.maxConns = n } }

func NewServer(addr string, opts ...Option) *Server {
    s := &Server{addr: addr, readTimeout: 5 * time.Second,
        writeTimeout: 10 * time.Second, maxConns: 100}
    for _, o := range opts {
        o(s)
    }
    return s
}

Reach for an explicit builder only when configuration steps genuinely validate against each other.

init() and global state

init() order (file declaration then filename order) is fragile, errors either panic or log.Fatal, and side effects before main make tests unpredictable:

go
var db *sql.DB
func init() { var err error; db, err = sql.Open("postgres", os.Getenv("DATABASE_URL")); ... } // bad

func NewUserRepository(db *sql.DB) *UserRepository { return &UserRepository{db: db} }       // good

Enums

go
type Status int
const (
    StatusUnknown Status = iota // 0 = unset
    StatusActive
    StatusInactive
)

Compile regexp once; embed static assets

go
var emailRegex = regexp.MustCompile(`^...$`)   // package level, once

//go:embed templates/*
var templateFS embed.FS

Panic vs error, concretely

  • Return error: network failures, missing rows, invalid input — anything a caller can act on.
  • Panic: nil where the code proved it impossible, violated invariants, Must* at init time.
  • Close/Flush errors: read-only cleanup can defer f.Close(), but durability-sensitive writes must report close/flush errors.

string vs []byte vs []rune

TypeDefault forReach for it
stringDisplay, keysImmutability and safety
[]byteI/Oio.Writer, building, mutation
[]runeUnicode opslen() must mean characters

Conversions allocate — stay in one type until you genuinely need another.

Iterators and streaming

Go 1.23+ range-able iterators give lazy evaluation — don't load a million rows into memory. Stream large transfers (DB to HTTP) so memory stays flat; see the data-handling reference for shapes.

Timeouts and retries

go
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
resp, err := httpClient.Do(req.WithContext(ctx))

Retry loops must check ctx.Err() between attempts and park on ctx.Done() during backoff. Long loops check ctx.Err() periodically.

Graceful shutdown and pools

Serve/worker loops tie their lifecycle to a context.Context; on cancel, stop accepting work, drain in-flight requests, then exit. Pool/lifetime patterns and runtime.AddCleanup usage: `references/resource-management.md`.

Database patterns

Wiring, transactions, nullables, pools, repository shapes: golang-database.

Architecture

Ask which style the project uses — clean, hexagonal, DDD, or flat — and don't impose ceremony on a small project. Non-negotiables regardless of style:

  • Domain layer stays free of framework imports.
  • Validate at boundaries (fail fast), trust internal code.
  • Make illegal states unrepresentable with types.
  • Respect 12-factor principles (golang-project-layout).

Per-style guides: `architecture.md`, `clean-architecture.md`, `hexagonal-architecture.md`, `ddd.md`.

Reference files

Cross-references

  • golang-data-structures — structure selection and internals.
  • golang-error-handling — wrapping, sentinels, single handling rule.
  • golang-structs-interfaces — interface design and composition.
  • golang-concurrency — goroutine lifecycle and graceful shutdown.
  • golang-context — timeout and cancellation patterns.
  • golang-project-layout — architecture and directory structure.
  • golang-refactoring — staging a migration toward these patterns safely.
do mesmo repositório

Mais Skills

Todos os Skills
fabianoflorentino
Comunidade

golang-google-wire

Compile-time dependency injection in Golang using google/wire — wire.NewSet, wire.Build, wire.Bind (interface→concrete), wire.Struct, wire.Value, wire.InterfaceValue, wire.FieldsOf, cleanup functions, //go:build wireinject injector files, and generated wiregen.go. Apply when using or adopting google/wire, when the codebase imports github.com/google/wire, or when wiring an application graph at compile time via wire.Build. For runtime DI with reflection, see fabianoflorentino/golang-agent-skills@golang-uber-dig skill.

instalações
1
GitHub Stars
0
Atualizado
14 de set.
fabianoflorentino
Comunidade

golang-lint

Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user mentions golangci-lint, go vet, staticcheck, or revive. Not for wiring a lint step into a GitHub Actions pipeline (→ See fabianoflorentino/golang-agent-skills@golang-continuous-integration skill).

instalações
1
GitHub Stars
0
Atualizado
14 de set.
fabianoflorentino
Comunidade

golang-modernize

Modernize Golang code to use recent language features, standard library improvements, and idiomatic patterns. Use when reviewing Go code with old-style patterns, when encountering a deprecation warning, or when the user asks for modernization, a Go version upgrade (e.g. to Go 1.27), or a CI/tooling refresh. Not for structural refactors, extracting functions, or moving code between packages (→ See fabianoflorentino/golang-agent-skills@golang-refactoring skill).

instalações
1
GitHub Stars
0
Atualizado
14 de set.
fabianoflorentino
Comunidade

golang-pitfalls-concurrency-foundations

Golang concurrency foundations — concurrency vs parallelism, thinking concurrency is always faster, channels vs mutexes, not understanding race problems (data race vs race condition), not understanding workload types (CPU vs I/O bound, GOMAXPROCS), and misunderstanding Go contexts. Distilled from mistakes 55-60 of 100 Go Mistakes and How to Avoid Them. Apply when reasoning about basic Golang concurrency, goroutines, and context usage.

instalações
1
GitHub Stars
0
Atualizado
14 de set.