Complete Go microservice implementing hexagonal architecture, DDD patterns, CQRS, and event-driven design for user management with dual REST/gRPC interfaces.
A comprehensive Go microservice template implementing hexagonal architecture and Domain-Driven Design patterns for user management. Features CQRS pattern, event-driven architecture, and dual REST/gRPC interfaces.
**Hexagonal Architecture Layers:**
**Key Components:**
Create the following directory structure:
```
users-app/
├── api/
│ ├── users.yml # OpenAPI specification
│ └── users.proto # Protocol Buffers definition
├── internal/
│ ├── domain/
│ │ ├── user.go # Domain entities and interfaces
│ │ └── events.go # Domain events
│ ├── service/
│ │ ├── command.go # Command service (CQRS write)
│ │ └── query.go # Query service (CQRS read)
│ ├── adapters/
│ │ ├── repository.go # Database implementation
│ │ ├── redis.go # Event publishing
│ │ └── logging.go # Event logging
│ ├── ports/
│ │ ├── http.go # REST API server
│ │ └── grpc.go # gRPC server
│ └── gen/ # Generated code (don't edit manually)
├── docker-compose.yml
├── Dockerfile
├── Makefile
├── .env.example
└── main.go
```
1. **Install Dependencies:**
```bash
go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@latest
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go install github.com/gotestyourself/gotestsum@latest
```
2. **Environment Configuration:**
```bash
cp .env.example .env
```
3. **Generate Code:**
```bash
make generate
```
4. **Start Services:**
```bash
make up
make down
```
**Multi-layer Testing Approach:**
```bash
make test
cd internal && go test ./...
export DB_TEST_HOST=localhost
```
**Command Service (Write Operations):**
```go
// service/command.go
type UsersCommandService struct {
repo domain.UserRepository
eventPublisher domain.EventPublisher
}
func (s *UsersCommandService) CreateUser(cmd CreateUserCommand) error {
user := domain.NewUser(cmd.Name, cmd.Email)
err := s.repo.Save(user)
if err != nil {
return err
}
event := domain.UserCreatedEvent{UserID: user.ID}
return s.eventPublisher.Publish(event)
}
```
**Query Service (Read Operations):**
```go
// service/query.go
type UsersQueryService struct {
repo domain.UserRepository
}
func (s *UsersQueryService) GetUser(id string) (*domain.User, error) {
return s.repo.FindByID(id)
}
```
**Rich Domain Models:**
```go
// domain/user.go
type User struct {
ID string
Name string
Email string
}
func NewUser(name, email string) *User {
return &User{
ID: generateID(),
Name: name,
Email: email,
}
}
func (u *User) UpdateEmail(email string) error {
if !isValidEmail(email) {
return errors.New("invalid email")
}
u.Email = email
return nil
}
```
**Repository Pattern:**
```go
// domain/repository.go
type UserRepository interface {
Save(user *User) error
FindByID(id string) (*User, error)
FindAll() ([]*User, error)
Delete(id string) error
}
```
**Domain Events:**
```go
// domain/events.go
type Event interface {
EventType() string
Timestamp() time.Time
}
type UserCreatedEvent struct {
UserID string `json:"user_id"`
Timestamp time.Time `json:"timestamp"`
}
func (e UserCreatedEvent) EventType() string {
return "user.created"
}
```
**Event Publishing:**
```go
// adapters/redis.go
type RedisEventPublisher struct {
client *redis.Client
}
func (r *RedisEventPublisher) Publish(event domain.Event) error {
data, _ := json.Marshal(event)
return r.client.Publish(ctx, "events", data).Err()
}
```
**Health Check:**
```bash
curl -v http://localhost:8080/health
```
**gRPC Testing:**
```bash
make evans
```
Create a comprehensive Makefile:
```makefile
.PHONY: up down generate test evans
up:
docker-compose up -d
down:
docker-compose down
generate:
# Generate OpenAPI code
oapi-codegen -package api -generate types,server api/users.yml > internal/gen/api/types.go
# Generate gRPC code
protoc --go_out=internal/gen/grpc --go-grpc_out=internal/gen/grpc api/users.proto
test:
gotestsum ./internal/...
evans:
evans --host localhost --port 9090 -r repl
```
1. **Generated Code**: Never manually edit files in `internal/gen/` - regenerate using `make generate`
2. **Event Flow**: Command → Event → Redis publication + File logging
3. **Infrastructure**: Uses PostgreSQL for persistence, Redis for event publishing
4. **Configuration**: Environment-driven with `.env` file support
5. **Dual Protocols**: Supports both REST HTTP and gRPC simultaneously
This architecture provides a solid foundation for building scalable, maintainable microservices following industry best practices and clean architecture principles.
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/go-hexagonal-architecture-user-service/raw