con un clic
golang-ddd
This skill should be used when implementing DDD tactical design patterns in Go, including Entities, Value Objects, Aggregates, Repositories, Domain Services, Domain Events, Factories, and Specifications.
Menú
This skill should be used when implementing DDD tactical design patterns in Go, including Entities, Value Objects, Aggregates, Repositories, Domain Services, Domain Events, Factories, and Specifications.
This skill should be used when the user asks about libraries, frameworks, API references, or needs code examples. Activates for setup questions, code generation involving libraries, or mentions of specific frameworks like React, Vue, Next.js, Prisma, Supabase, etc.
Implement Domain-Driven Design tactical patterns in C#/.NET. Use when building Entities, Value Objects, Aggregates, Domain Events, Repositories, or structuring a DDD solution. Framework-agnostic — covers pure domain modeling with modern C#.
Write integration tests in Go using testcontainers-go with real databases, caches, and message queues in Docker containers. Covers PostgreSQL, MySQL, Redis, RabbitMQ, Kafka, and custom containers with idiomatic Go testing patterns.
| name | golang-ddd |
| description | This skill should be used when implementing DDD tactical design patterns in Go, including Entities, Value Objects, Aggregates, Repositories, Domain Services, Domain Events, Factories, and Specifications. |
| license | MIT |
| metadata | {"version":"1.0.0","domain":"architecture","triggers":"ddd golang, domain driven design go, aggregate go, entity go, value object go, repository pattern go, domain events go, ddd tactical","role":"specialist","scope":"implementation","output-format":"code"} |
To guide implementation of Domain-Driven Design tactical patterns in idiomatic Go. This skill covers Entities, Value Objects, Aggregates, Repositories, Domain Services, Domain Events, Factories, and Specifications using Go-native idioms (composition over inheritance, interfaces, unexported fields, functional options).
*T receiversT receiversNewX() constructors to enforce invariants at creationinternal/domain/context.Context as first parameter in repository and service methodsinternal/
├── domain/ # Domain layer (no external deps)
│ ├── customer/ # One package per aggregate
│ │ ├── customer.go # Aggregate root entity
│ │ ├── repository.go # Repository interface
│ │ ├── email.go # Value objects
│ │ ├── events.go # Domain events
│ │ └── errors.go # Domain errors
│ ├── order/
│ │ ├── order.go
│ │ ├── repository.go
│ │ ├── item.go # Child entity
│ │ └── money.go # Value object
│ └── shared/ # Shared kernel
│ ├── events.go # Event interface
│ └── specification.go # Generic specification
│
├── application/ # Application services (orchestration)
│ ├── command/
│ │ └── place_order.go
│ └── query/
│ └── get_customer.go
│
└── infrastructure/ # Technical implementations
├── postgres/
│ ├── customer_repo.go
│ └── order_repo.go
└── eventbus/
└── in_memory.go
Dependency rule: Domain has zero imports from application or infrastructure. Dependencies point inward.
| Pattern | Go Idiom | Receiver | Identity |
|---|---|---|---|
| Entity | Struct + pointer receiver | *T | By ID |
| Value Object | Type alias or struct + value receiver | T | By value |
| Aggregate Root | Entity + unexported children | *T | By ID |
| Repository | Interface in domain package | N/A | N/A |
| Domain Service | Stateless struct with deps | *T or func | N/A |
| Domain Event | Immutable struct | T (value) | By name+time |
| Factory | NewX() function | N/A | N/A |
| Specification | Generic interface IsSatisfiedBy(T) bool | T or *T | N/A |
When implementing a new aggregate or domain concept:
Email, Money, Address)infrastructure/ packageFor detailed implementation guides with full code examples, see:
references/entities-and-value-objects.md - Entities, Value Objects, and Factoriesreferences/aggregates-and-repositories.md - Aggregates, Repositories, and Domain Servicesreferences/events-and-specifications.md - Domain Events and Specificationsreferences/anti-patterns.md - Common mistakes and how to avoid themEntities have unique identity and mutable state. Use unexported fields, pointer receivers, and factory functions.
type Order struct {
id uuid.UUID
status Status
items []Item
createdAt time.Time
}
func NewOrder(customerID uuid.UUID) (*Order, error) {
return &Order{
id: uuid.New(),
status: StatusDraft,
items: make([]Item, 0),
createdAt: time.Now(),
}, nil
}
func (o *Order) AddItem(product ProductID, qty int, price Money) error {
if o.status != StatusDraft {
return ErrOrderNotDraft
}
o.items = append(o.items, NewItem(product, qty, price))
return nil
}
Immutable types validated at creation. Use value receivers. Return new instances for operations.
type Money struct {
amount int64
currency string
}
func NewMoney(amount int64, currency string) (Money, error) {
if currency == "" {
return Money{}, ErrInvalidCurrency
}
return Money{amount: amount, currency: currency}, nil
}
func (m Money) Add(other Money) (Money, error) {
if m.currency != other.currency {
return Money{}, ErrCurrencyMismatch
}
return Money{amount: m.amount + other.amount, currency: m.currency}, nil
}
Aggregate roots enforce invariants across child entities. All mutations go through the root.
func (o *Order) Place() error {
if len(o.items) == 0 {
return ErrEmptyOrder
}
if o.status != StatusDraft {
return ErrOrderNotDraft
}
o.status = StatusPlaced
o.events = append(o.events, NewOrderPlacedEvent(o.id, o.Total()))
return nil
}
Interface in domain, implementation in infrastructure. One repository per aggregate root.
// domain/order/repository.go
type Repository interface {
Find(ctx context.Context, id uuid.UUID) (*Order, error)
Save(ctx context.Context, order *Order) error
Update(ctx context.Context, id uuid.UUID, fn func(*Order) error) error
}
Immutable structs collected by aggregates, published by application layer.
type OrderPlaced struct {
orderID uuid.UUID
total Money
occurredAt time.Time
}
func (o *Order) PullEvents() []Event {
events := o.events
o.events = nil
return events
}
Stateless operations spanning multiple aggregates. Domain logic only, no orchestration.
type TransferService struct {
accountRepo account.Repository
}
func (s *TransferService) Transfer(ctx context.Context, from, to uuid.UUID, amount Money) error {
// Load aggregates, validate domain rules, coordinate changes
}
Composable business rules using Go generics.
type Specification[T any] interface {
IsSatisfiedBy(T) bool
}
func And[T any](specs ...Specification[T]) Specification[T] { /* ... */ }
func Or[T any](specs ...Specification[T]) Specification[T] { /* ... */ }
func Not[T any](spec Specification[T]) Specification[T] { /* ... */ }
SetStatus() with domain methods like Place(), Cancel(), Ship()Reconstruct() functions for loading from DB (bypass validation)var ErrNotFound = errors.New(...)) per aggregate packageDetailed guides with full code examples are in the references/ directory.