Menu
Dev.to #architectureยทMarch 7, 2026

Clean Architecture for Go APIs with Dependency Injection

This article demonstrates building a REST API in Go using Clean Architecture principles, emphasizing separation of concerns. It details a layered design to isolate business logic from infrastructure details like databases and web frameworks, making the system more testable and maintainable. The guide uses SQLite for persistence and the Ore dependency injection container to manage wiring.

Read original on Dev.to #architecture

The article focuses on implementing Clean Architecture, a software design principle that structures an application into independent layers. The core idea is that dependencies should always point inward, meaning inner layers (like domain logic) have no knowledge of outer layers (like databases or UI frameworks). This promotes testability, maintainability, and flexibility by making the system independent of specific technologies.

The Four Layers of Clean Architecture

Clean Architecture organizes code into distinct layers, each with a specific responsibility. The independence of these layers is crucial for isolating business rules from external concerns.

  • Domain Layer: Contains core business entities and interfaces (contracts) for external services like repositories. It has zero external dependencies.
  • Application Layer: Implements use cases and orchestrates domain entities. It depends on the domain layer but is oblivious to infrastructure details.
  • Presentation Layer: Handles user interaction, such as HTTP requests in an API. It depends on the application layer.
  • Infrastructure Layer: Provides concrete implementations for interfaces defined in the domain layer, such as SQLite repositories or HTTP server setup. It depends on the domain and application layers via interfaces.
๐Ÿ’ก

Dependency Inversion in Practice

In Go, interfaces are key to achieving dependency inversion. The domain defines an interface (e.g., `BookRepository`), and the infrastructure provides its concrete implementation (e.g., `SQLiteBookRepository`). The application layer then depends only on the interface, not the concrete implementation. This allows the persistence mechanism to be swapped without altering business logic.

Dependency Injection with Ore

The article uses Ore, a lightweight dependency injection container for Go, to manage the wiring of these layers. Ore acts as the composition root, which is the single place where all dependencies are resolved and injected, typically at application startup. This prevents layers from instantiating their dependencies directly, further enforcing the inward-pointing dependency rule and making components easier to test in isolation.

plaintext
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Presentation (HTTP) โ”‚ โ† knows application
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Application (Use Cases) โ”‚ โ† knows domain
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Domain (Entities + Interfaces) โ”‚ โ† knows nothing
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Infrastructure (SQLite, etc.) โ”‚ โ† knows domain interfaces
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ†‘ Dependencies point inward โ†‘
Clean ArchitectureGoAPIRESTDependency InjectionSoftware ArchitectureSQLiteLayered Architecture

Comments

Loading comments...