A Go application template with Hexagonal Architecture (Ports & Adapters)
This project uses Hexagonal Architecture (also known as Ports & Adapters Pattern) which separates business logic from external dependencies.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Delivery Layer β
β (HTTP Handlers, Routes, Middleware) β
βββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ
β Core Domain β
β (Business Logic, Use Cases, Entities) β
βββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββ
β Persistence Layer β
β (Repositories, Database, Storage) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Contains business logic that is independent from frameworks and external dependencies.
- Domain: Entities and business rules
- Port: Interfaces for repositories and services
- UseCase: Business logic implementation
Concrete implementations of ports that interact with the outside world.
- Delivery: HTTP handlers, routes, middleware
- Persistence: Database implementation (inmemory, sqlite, mysql, etc.)
- Config: Application configuration
Application composition using Wire for dependency injection.
server/
βββ cmd/
β βββ server/
β βββ main.go # Application entry point
βββ internal/
β βββ adapter/ # Adapter Layer
β β βββ config/ # Configuration
β β β βββ app.go
β β β βββ config.go
β β β βββ http.go
β β βββ delivery/ # Delivery adapters
β β β βββ http/
β β β βββ router.go # HTTP router setup
β β β βββ todo_handler.go # Todo HTTP handlers
β β β βββ todo_routes.go # Todo routes registration
β β β βββ validator.go # Request validation
β β β βββ dto/ # Data Transfer Objects
β β β βββ helper/ # HTTP helpers
β β β βββ middleware/ # HTTP middleware
β β βββ persistence/ # Persistence adapters
β β βββ inmemory/ # In-memory repository
β β β βββ todo_repository.go
β β βββ sqlite/ # SQLite repository (future)
β βββ app/ # Application composition
β β βββ http_app.go # HTTP application
β β βββ wire.go # Wire providers
β β βββ wire_gen.go # Wire generated code
β βββ core/ # Core Domain Layer
β β βββ domain/ # Domain entities
β β β βββ errors.go # Domain errors
β β β βββ todo.go # Todo entity
β β βββ port/ # Ports (interfaces)
β β β βββ todo_repository.go # Repository interface
β β β βββ todo_service.go # Service interface
β β βββ usecase/ # Use cases
β β βββ todo/
β β βββ service.go # Todo service implementation
β β βββ create.go
β β βββ delete.go
β β βββ get.go
β β βββ list.go
β β βββ list_paginated.go
β β βββ mark_done.go
β β βββ mark_undone.go
β β βββ update.go
β βββ shared/ # Shared utilities
β βββ ptr/
β βββ ptr.go # Pointer helpers
βββ go.mod # Go module definition
βββ go.sum # Go dependencies
βββ README.md # This file
βββ .env.example # env example
Request β Handler β Service Interface β Use Case β Repository Interface β Storage
β β β β β β
Echo TodoHandler TodoService Service Impl TodoRepository InMemory
(Adapter) (Adapter) (Port) (Core) (Port) (Adapter)
Key Principle: Adapters depend on Core, Core never depends on Adapters.
- Go 1.21+ - Programming language
- Echo v4 - High performance HTTP framework
- Wire - Compile-time dependency injection
- Validator - Struct and field validation
- Go 1.21 or higher
- Wire (for dependency injection)
Install Wire:
go install github.com/google/wire/cmd/wire@latestgit clone https://github.com/0xirvan/hexagonal-architecture.git
cd hexagonal-architecture/serverIf you want to use your own module name:
# Update go.mod
go mod edit -module github.com/yourusername/yourproject/server
# Update all imports
find . -type f -name "*.go" -exec sed -i 's|github.com/0xirvan/hexagonal-architecture/server|github.com/yourusername/yourproject/server|g' {} +
# Tidy dependencies
go mod tidy
go mod downloadwire ./internal/appcp .env.example .envgo run cmd/server/main.goServer will run on http://localhost:8080
- Hexagonal Architecture - Core isolation from external dependencies
- Repository Pattern - Data access abstraction
- Service Layer Pattern - Business logic encapsulation with interface
- Dependency Injection - Loose coupling via Wire
- DTO Pattern - Data transfer between layers
- Port & Adapter Pattern - Interface-based boundaries
To switch from in-memory to SQLite:
- Implement SQLite repository in
internal/adapter/persistence/sqlite/ - Update Wire in
internal/app/wire.go:
var repositorySet = wire.NewSet(
sqlite.NewTodoRepository, // Change from inmemory
)- Regenerate Wire:
wire ./internal/app
- Fork the project
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
0xirvan
- GitHub: @0xirvan
- Hexagonal Architecture concept by Alistair Cockburn
- Built with β€οΈ using Go and Echo framework
- Special thanks to the Go community for excellent tools and libraries
β If you find this project helpful, please consider giving it a star!