skills/333-333-333/agents/go-repository-pattern

go-repository-pattern

SKILL.md

When to Use

  • Creating a new repository for a domain aggregate
  • Implementing PostgreSQL adapter with sqlc
  • Writing database migrations
  • Setting up database connection and pooling
  • Adding transactional support
  • Creating in-memory repository for local dev / unit tests

Critical Patterns

Pattern Rule
Interface in domain Repository interface lives in domain/port.go
sqlc for PostgreSQL Write SQL, generate type-safe Go code — no ORMs, no manual scanning
In-memory for local/tests Pure Go map implementation for zero-dep development
Migrations versioned Use golang-migrate with sequential numbered files
Each service owns its DB No shared databases between microservices
Context everywhere All repository methods accept context.Context as first parameter
Domain ≠ DB model sqlc generates DB structs; map them to domain entities in the adapter

Architecture

internal/{domain}/
  domain/
    port.go                    # Repository interface (what the domain needs)
  infrastructure/
    repository/
      query.sql                # SQL queries with sqlc annotations
      sqlc.yaml                # sqlc configuration
      db/                      # Generated by sqlc — DO NOT EDIT
        models.go              # DB structs
        query.sql.go           # Type-safe query functions
        db.go                  # DBTX interface
      postgres.go              # Adapter: implements domain port using sqlc
      memory.go                # In-memory implementation

Domain Port (Interface)

See assets/port.go

sqlc Setup

Configuration

See assets/sqlc.yaml

SQL Queries

See assets/query.sql

Generated Code (DO NOT EDIT)

sqlc generates:

See assets/models_generated.go

See assets/query_generated.go

PostgreSQL Adapter (uses sqlc)

See assets/postgres.go

In-Memory Implementation (Local + Unit Tests)

See assets/memory.go

When to Use Which Implementation

Context Implementation Why
Unit tests In-memory Zero deps, instant, tests domain logic
Local dev without Docker In-memory No Postgres needed, fast startup
Local dev with Docker PostgreSQL (sqlc) Validate real SQL
Integration tests PostgreSQL via testcontainers Validate real SQL in CI
dev / staging / production PostgreSQL (sqlc) Real persistence

Wiring by Environment

See assets/wiring.go

Database Connection (pgx pool)

See assets/database.go

Migrations

Use golang-migrate:

migrations/
  000001_create_users.up.sql
  000001_create_users.down.sql

See assets/migration_up.sql

See assets/migration_down.sql

Transactions with sqlc

See assets/transactions.go

Commands

# Install sqlc CLI
brew install sqlc

# Generate code from SQL
cd internal/{domain}/infrastructure/repository && sqlc generate

# Verify generated code
go build ./...

# Install pgx driver
go get github.com/jackc/pgx/v5
go get github.com/jackc/pgx/v5/pgxpool

# Install migrate CLI
brew install golang-migrate

# Create migration
migrate create -ext sql -dir migrations -seq create_users

# Run migrations
migrate -path migrations -database "postgres://user:pass@localhost:5432/dbname?sslmode=disable" up

# Rollback
migrate -path migrations -database "..." down 1

Makefile Targets

See assets/Makefile

Anti-Patterns

Don't Do
Edit generated db/ files Edit query.sql and run sqlc generate
Import sqlc/pgx in domain Domain defines interface, infra implements with sqlc
Use GORM or other ORMs Use sqlc — you write SQL, it generates type-safe Go
Use sqlx for new code Use sqlc + pgx — better type safety, less boilerplate
Shared database between services Each service owns its schema
Return pgx.ErrNoRows to application Map to domain error like ErrUserNotFound
Use sqlc structs as domain entities Map sqlc structs to domain entities in the adapter
Skip in-memory implementation Always provide in-memory for fast local dev + unit tests
Weekly Installs
1
First Seen
6 days ago
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
kiro-cli1