DEV Community

Kittipat.po
Kittipat.po

Posted on β€’ Edited on

2 1 1 1 1

Structuring a Go Project with Clean Architecture β€” A Practical Example

Clean Architecture

🧠 Applying Clean Architecture in Go β€” A Real-World Project Walkthrough

Clean Architecture is a popular approach for building scalable and maintainable backend systems. However, applying it effectively β€” especially in real-world projects β€” can feel overwhelming without concrete examples.

In this post, I’d like to share how I’ve applied Clean Architecture principles in a simple Go project called 🎟️ Ticket Reservation System. It’s a small concert ticket booking service, and while not exhaustive, it demonstrates one possible way to organize code using Clean Architecture. The project includes features like domain-driven modeling, repository interfaces, CLI tooling, Swagger documentation, and modular routing.

If you’re looking for a starting point to apply Clean Architecture in your own Go projects, this layout might offer a useful reference.

🧭 Why Clean Architecture?

Clean architecture promotes separation of concerns, testability, and clear boundaries between core business logic and external dependencies like databases, HTTP frameworks, or third-party APIs.

This means:

  • Business logic doesn’t depend on frameworks.
  • Infrastructure can change without rewriting your use cases.
  • Handlers, services, and domain models remain isolated and testable.

🧱 Folder Structure Breakdown

Here’s the high-level layout of the ticket-reservation project:

ticket-reservation/
β”œβ”€β”€ cmd/                          # Application entry points and CLI commands
β”‚   β”œβ”€β”€ root.go                   # Root command for the CLI
β”‚   β”œβ”€β”€ serve_cmd.go              # Command to start the server
β”‚   β”œβ”€β”€ migrate_cmd.go            # Command to run database migrations
β”‚   β”œβ”€β”€ new_migration_cmd.go      # Command to create new migration files
β”‚   β”œβ”€β”€ print_config_cmd.go       # Command to print the current configuration
β”‚   └── generate_sql_builder.go   # Command to generate SQL builder files
β”‚   └── ...                       # Other commands
β”œβ”€β”€ db/                           # Database-related files
β”‚   └── migrations/               # Database migration files
β”œβ”€β”€ docs/                         # Documentation files
β”‚   β”œβ”€β”€ swagger.yaml              # API documentation in Swagger format
β”‚   └── ...                       # Other design and architecture documents
β”œβ”€β”€ internal/                     # Internal application code
β”‚   β”œβ”€β”€ api/                      # Delivery layer
β”‚   β”‚   └── http/                 # HTTP API components
β”‚   β”‚       β”œβ”€β”€ handler/          # HTTP handlers by domain
β”‚   β”‚       β”‚   β”œβ”€β”€ healthcheck/  # Health check handlers
β”‚   β”‚       β”‚   └── ...           # Other domain handlers
β”‚   β”‚       β”œβ”€β”€ middleware/       # HTTP middleware
β”‚   β”‚       └── route/            # HTTP route definitions
β”‚   β”œβ”€β”€ config/                   # Application configuration
β”‚   β”œβ”€β”€ domain/                   # Domain layer
β”‚   β”‚   β”œβ”€β”€ cache/                # Cache-related interfaces
β”‚   β”‚   β”œβ”€β”€ entity/               # Domain models (e.g., Concert, Reservation)
β”‚   β”‚   β”œβ”€β”€ errs/                 # Domain-specific errors
β”‚   β”‚   └── repository/           # Repository interfaces
β”‚   β”œβ”€β”€ infra/                    # Infrastructure layer
β”‚   β”‚   β”œβ”€β”€ db/                   # Database implementations
β”‚   β”‚   β”‚   β”œβ”€β”€ connection.go     # Database connection setup
β”‚   β”‚   β”‚   β”œβ”€β”€ sql_execer.go     # SQL execution interface
β”‚   β”‚   β”‚   β”œβ”€β”€ transactor.go     # Transaction management
β”‚   β”‚   β”‚   β”œβ”€β”€ mocks/            # Mock implementations
β”‚   β”‚   β”‚   β”œβ”€β”€ model_gen/        # Generated models from DB schema
β”‚   β”‚   β”‚   └── repository/       # Repository implementations
β”‚   β”‚   β”‚       β”œβ”€β”€ healthcheck/  # Health check repository
β”‚   β”‚   β”‚       └── ...           # Other repositories
β”‚   β”‚   └── redis/                # Redis implementations
β”‚   β”‚       β”œβ”€β”€ client.go         # Redis client interface
β”‚   β”‚       β”œβ”€β”€ connection.go     # Redis connection setup
β”‚   β”‚       β”œβ”€β”€ mocks/            # Mock implementations
β”‚   β”‚       └── repository/       # Repository implementations
β”‚   β”‚           β”œβ”€β”€ seat/         # Seat locking and cache implementations
β”‚   β”‚           └── ...           # Other repositories
β”‚   β”œβ”€β”€ server/                   # Server setup and initialization
β”‚   β”‚   β”œβ”€β”€ dependency.go         # Dependency injection
β”‚   β”‚   β”œβ”€β”€ middleware.go         # Server middleware
β”‚   β”‚   └── server.go             # HTTP server setup
β”‚   β”œβ”€β”€ usecase/                  # Application business logic
β”‚   β”‚   β”œβ”€β”€ healthcheck/          # Health check use case
β”‚   β”‚   └── ...                   # Other use cases
β”‚   └── util/                     # Utility functions
β”‚       β”œβ”€β”€ httpresponse/         # HTTP response helpers
β”‚       └── ...                   # Other utility functions
β”œβ”€β”€ pkg/                          # Shared helper packages
β”œβ”€β”€ docker-compose.yaml           # Docker Compose for local development
β”œβ”€β”€ Dockerfile                    # Docker build definition
β”œβ”€β”€ env.yaml                      # Environment variables configuration
β”œβ”€β”€ go.mod                        # Go module definition
β”œβ”€β”€ go.sum                        # Go module dependencies
β”œβ”€β”€ main.go                       # Main application entry point
β”œβ”€β”€ Makefile                      # Makefile for common tasks
└── README.md                     # Project documentation
Enter fullscreen mode Exit fullscreen mode

Let’s walk through some highlights πŸ‘‡

🧩 Clean Architecture in Action

1. Delivery Layer β€” internal/api/http/
This layer exposes the API using the Gin framework. It includes:

  • handler/: request parsing, validation, response formatting
  • middleware/: application-level HTTP middleware such as authentication
  • route/: HTTP route setup using injected dependencies

2. Usecase Layer β€” internal/usecase/
This layer contains pure application logic. It defines input/output structs and orchestrates repository calls or business rules. It does not depend on Gin, SQL, or any infra packages.

3. Domain Layer β€” internal/domain/
This is the heart of the application. It defines:

  • entity/: domain models like Concert, Reservation
  • repository/: abstract interfaces for data access
  • mocks/: auto-generated mocks for unit tests

No dependencies, no framework imports β€” just business terms and contracts.

4. Infrastructure Layer β€” internal/infra/
This layer implements database logic using go-jet and sqlx. It satisfies the interfaces defined in the domain layer.

πŸ› οΈ Built-in CLI Tools

This project comes with a built-in CLI (powered by Cobra) for common dev tasks. Run go run main.go --help to explore all commands.

Key commands:

  • serve: Start the HTTP server
  • migrate: Run database migrations
  • new-migration: Generate new migration files
  • print-config: Print current effective config
  • generate-db: Generate SQL builder and model files using go-jet

πŸ”„ Project Status

This project is still a work-in-progress, and not all features are complete. However, it already provides a useful reference for:

  • Structuring Go services with Clean Architecture
  • Organizing code for testability and scalability
  • Using tools like Cobra, Swagger, Jet, and MockGen effectively

If you’re starting a backend service in Go and want a clean, extensible foundation β€” feel free to fork or study this project. Feedback and contributions are welcome!
πŸ‘‰ GitHub Repo β€” ticket-reservation

Top comments (0)

DevCycle image

Fast, Flexible Releases with OpenFeature Built-in

Ship faster on the first feature management platform with OpenFeature built-in to all of our open source SDKs.

Start shipping

πŸ‘‹ Kindness is contagious

Explore this insightful write-up, celebrated by our thriving DEV Community. Developers everywhere are invited to contribute and elevate our shared expertise.

A simple "thank you" can brighten someone’s dayβ€”leave your appreciation in the comments!

On DEV, knowledge-sharing fuels our progress and strengthens our community ties. Found this useful? A quick thank you to the author makes all the difference.

Okay