external/cc-skills-golang/golang-design-patterns/SKILL.md
Idiomatic Golang design patterns — functional options, constructors, error flow and cascading, resource management and lifecycle, graceful shutdown, resilience, architecture, dependency injection, data handling, streaming, and more. Apply when explicitly choosing between architectural patterns, implementing functional options, designing constructor APIs, setting up graceful shutdown, applying resilience patterns, or asking which idiomatic Go pattern fits a specific problem.
npx skillsauth add seikaikyo/dash-skills golang-design-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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:
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-patternsskill takes precedence.
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.
init() — runs implicitly, cannot return errors, makes testing unpredictable. Use explicit constructorsdefer Close() immediately after opening — later code changes can accidentally skip cleanupruntime.AddCleanup over runtime.SetFinalizer — finalizers are unpredictable and can resurrect objectsstrings.Builder for concatenation in loops → see samber/cc-skills-golang@golang-code-style[]byte for mutation and I/O, string for display and keys — conversions allocate//go:embed for static assets — embeds at compile time, eliminates runtime file I/O errorscrypto/rand for keys/tokens — math/rand is predictable → see samber/cc-skills-golang@golang-securityvar _ Interface = (*Type)(nil)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.
init() and Mutable Globalsinit() runs implicitly, makes testing harder, and creates hidden dependencies:
init() functions run in declaration order, across files in filename alphabetical order — fragilelog.Fatalmain() 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}
}
Zero values should represent invalid/unset state:
type Status int
const (
StatusUnknown Status = iota // 0 = invalid/unset
StatusActive // 1
StatusInactive // 2
StatusSuspended // 3
)
// 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)
}
//go:embed for Static Assetsimport "embed"
//go:embed templates/*
var templateFS embed.FS
//go:embed version.txt
var version string
→ See samber/cc-skills-golang@golang-structs-interfaces for the var _ Interface = (*Type)(nil) pattern.
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.
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| 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.
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.
For code examples, see Data Handling Patterns.
defer Close() immediately after opening — don't wait, don't forget:
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close() // right here, not 50 lines later
rows, err := db.QueryContext(ctx, query)
if err != nil {
return err
}
defer rows.Close()
For graceful shutdown, resource pools, and runtime.AddCleanup, see Resource Management.
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
resp, err := httpClient.Do(req.WithContext(ctx))
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.
→ See samber/cc-skills-golang@golang-database skill for sqlx/pgx, transactions, nullable columns, connection pools, repository interfaces, testing.
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:
samber/cc-skills-golang@golang-project-layout| Guide | Scope | | --- | --- | | Architecture Patterns | High-level principles, when each architecture fits | | Clean Architecture | Use cases, dependency rule, layered adapters | | Hexagonal Architecture | Ports and adapters, domain core isolation | | Domain-Driven Design | Aggregates, value objects, bounded contexts |
samber/cc-skills-golang@golang-data-structures skill for data structure selection, internals, and container/ packagessamber/cc-skills-golang@golang-error-handling skill for error wrapping, sentinel errors, and the single handling rulesamber/cc-skills-golang@golang-structs-interfaces skill for interface design and compositionsamber/cc-skills-golang@golang-concurrency skill for goroutine lifecycle and graceful shutdownsamber/cc-skills-golang@golang-context skill for timeout and cancellation patternssamber/cc-skills-golang@golang-project-layout skill for architecture and directory structuresamber/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 codebasetools
Conduct comprehensive GDPR compliance assessments by evaluating data processing activities against EU Regulation 2016/679, including Article 30 records of processing, lawful basis validation, data subject rights implementation, Data Protection Impact Assessments (DPIAs) under Article 35, breach notification procedures, international transfer safeguards (SCCs, adequacy decisions), and technical/organizational measures under Article 32. Use when processing personal data of EU residents, preparing for supervisory authority audits, implementing privacy-by-design for new systems, scoping compliance gaps for M&A due diligence, assessing third-party processors, or responding to data subject access requests at scale. Incorporates 2026 guidance from ICO, EDPB, and post-Data (Use and Access) Act 2025 UK-GDPR considerations. Do not use for implementing specific Article 32 controls — use implementing-gdpr-data-protection-controls; or for DSAR automation — use implementing-gdpr-data-subject-access-request.
tools
Parse Windows forensic artifacts—$MFT/$J (MFTECmd), Prefetch (PECmd), registry hives (RECmd), shellbags, and Amcache—into normalized CSV/JSON with Eric Zimmerman's EZ Tools, then load results into Timeline Explorer for analysis. Use during DFIR/incident-response investigations, after triage collection (e.g. with KAPE), to establish program execution, file/folder access, and persistence evidence from acquired forensic images.
development
Build automated multi-turn adversarial attacks against conversational LLM targets using Microsoft PyRIT's RedTeamingOrchestrator, CrescendoOrchestrator (gradual escalation), and TreeOfAttacksWithPruningOrchestrator (adaptive branching), with scorer feedback loops and persisted conversation memory. Use when single-shot LLM scanning is insufficient and you need multi-turn, scorer-driven AI red-team campaigns against a chatbot or agent.
testing
Stand up MISP, enable and cache curated threat feeds (CIRCL, abuse.ch, Feodo Tracker), apply warninglists to suppress false positives, query indicators with PyMISP, and export attributes as auto-generated Suricata/Sigma/Wazuh detection rules. Use when maturing a MISP instance to actively drive detection, curating threat feeds with quality controls, or automating IOC-to-detection pipelines for the SIEM/IDS.