A production-ready Go project template following Clean Architecture and Domain-Driven Design principles, optimized for building scalable applications with PostgreSQL or MySQL.
- ποΈ Clean Architecture - Clear separation of concerns with domain, repository, use case, and presentation layers
- π¦ Modular Domain Structure - Easy to add new domains without affecting existing code
- π Dependency Injection - Centralized component wiring with lazy initialization
- ποΈ Multi-Database Support - PostgreSQL and MySQL with dedicated repository implementations
- π Database Migrations - Separate migrations for PostgreSQL and MySQL
- π UUIDv7 Primary Keys - Time-ordered, globally unique identifiers
- πΌ Transaction Management - Built-in support for database transactions
- π¬ Transactional Outbox Pattern - Event-driven architecture with guaranteed delivery
β οΈ Standardized Error Handling - Domain errors with proper HTTP status code mapping- β Input Validation - Advanced validation with custom rules (email, password strength, etc.)
- π Password Hashing - Secure Argon2id password hashing
- π§ͺ Integration Testing - Real database tests instead of mocks
- π³ Docker Support - Multi-stage Dockerfile and Docker Compose setup
- π¦ CI/CD Ready - GitHub Actions workflow with comprehensive testing
- π Structured Logging - JSON logs using slog
- π οΈ Comprehensive Makefile - Easy development and deployment commands
- π Getting Started - Installation and setup guide
- ποΈ Architecture - Architectural patterns and design principles
- π οΈ Development - Development workflow and coding standards
- π§ͺ Testing - Testing strategies and best practices
β οΈ Error Handling - Error handling system guide- β Adding Domains - Step-by-step guide to add new domains
- Go 1.25+
- PostgreSQL 12+ or MySQL 8.0+
- Docker and Docker Compose (optional)
# Clone the repository
git clone https://github.com/allisson/go-project-template.git
cd go-project-template
# Install dependencies
go mod download
# Start a database (using Docker)
make dev-postgres # or make dev-mysql
# Run migrations
make run-migrate
# Start the server
make run-serverThe server will be available at http://localhost:8080
For detailed setup instructions, see the Getting Started Guide.
go-project-template/
βββ cmd/app/ # Application entry point
βββ internal/
β βββ app/ # Dependency injection container
β βββ config/ # Configuration management
β βββ database/ # Database connection and transactions
β βββ errors/ # Standardized domain errors
β βββ http/ # HTTP server infrastructure
β βββ httputil/ # HTTP utilities (JSON responses, error mapping)
β βββ validation/ # Custom validation rules
β βββ testutil/ # Test utilities
β βββ user/ # User domain module
β β βββ domain/ # User entities and domain errors
β β βββ usecase/ # User business logic
β β βββ repository/ # User data access
β β βββ http/ # User HTTP handlers and DTOs
β βββ outbox/ # Outbox domain module
β βββ domain/ # Outbox entities and domain errors
β βββ usecase/ # Outbox event processing logic
β βββ repository/ # Outbox data access
βββ migrations/
β βββ postgresql/ # PostgreSQL migrations
β βββ mysql/ # MySQL migrations
βββ docs/ # Documentation
βββ Dockerfile
βββ Makefile
βββ docker-compose.test.yml
Learn more about the architecture in the Architecture Guide.
# Start test databases
make test-db-up
# Run all tests
make test
# Run tests with coverage
make test-coverage
# Stop test databases
make test-db-down
# Or run everything in one command
make test-with-dbThe project uses real PostgreSQL and MySQL databases for testing instead of mocks. See the Testing Guide for details.
make build # Build the application
make run-server # Run HTTP server
make run-worker # Run outbox event processor
make run-migrate # Run database migrations
make lint # Run linter with auto-fix
make clean # Clean build artifactscurl http://localhost:8080/healthcurl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "john@example.com",
"password": "SecurePass123!"
}'For more development workflows, see the Development Guide.
- Domain Layer π― - Business entities and rules (pure, no external dependencies)
- Repository Layer πΎ - Data persistence (separate MySQL and PostgreSQL implementations)
- Use Case Layer πΌ - Business logic and orchestration
- Presentation Layer π - HTTP handlers and DTOs
- Utility Layer π οΈ - Shared utilities (error handling, validation, HTTP helpers)
The project uses a standardized error handling system:
- Standard Errors:
ErrNotFound,ErrConflict,ErrInvalidInput,ErrUnauthorized,ErrForbidden - Domain Errors: Wrap standard errors with domain-specific context
- Automatic HTTP Mapping: Domain errors automatically map to appropriate HTTP status codes
Example:
// Define domain error
var ErrUserNotFound = errors.Wrap(errors.ErrNotFound, "user not found")
// Use in repository
if errors.Is(err, sql.ErrNoRows) {
return nil, domain.ErrUserNotFound // Maps to 404 Not Found
}Learn more in the Error Handling Guide.
All entities use UUIDv7 for primary keys:
- β±οΈ Time-ordered for better database performance
- π Globally unique across distributed systems
- π Better than UUIDv4 for database indexes
Ensures reliable event delivery using a use case-based approach:
- Business operation and event stored in same transaction
- Outbox use case processes pending events with configurable retry logic
- Guarantees at-least-once delivery
- Extensible event processing via the
EventProcessorinterface
# Build Docker image
make docker-build
# Run server in Docker
make docker-run-server
# Run worker in Docker
make docker-run-worker
# Run migrations in Docker
make docker-run-migrateThe worker command runs the outbox event processor, which handles asynchronous event processing using the transactional outbox pattern.
All configuration is done via environment variables. Create a .env file in your project root:
DB_DRIVER=postgres
DB_CONNECTION_STRING=postgres://user:password@localhost:5432/mydb?sslmode=disable
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
LOG_LEVEL=infoSee the Getting Started Guide for all available configuration options.
Adding a new domain is straightforward:
- Create domain structure (
domain/,usecase/,repository/,http/) - Define domain entity and errors
- Create database migrations
- Implement repositories (PostgreSQL and MySQL)
- Implement use case with business logic
- Create DTOs and HTTP handlers
- Register in DI container
- Wire HTTP routes
See the Adding Domains Guide for a complete step-by-step tutorial.
- google/uuid - UUID generation (UUIDv7 support)
- jellydator/validation - Advanced input validation
- urfave/cli - CLI framework
- allisson/go-env - Environment configuration
- allisson/go-pwdhash - Argon2id password hashing
- golang-migrate/migrate - Database migrations
- lib/pq - PostgreSQL driver
- go-sql-driver/mysql - MySQL driver
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
This template leverages these excellent Go libraries:
- github.com/allisson/go-env
- github.com/allisson/go-pwdhash
- github.com/jellydator/validation
- github.com/google/uuid
- github.com/urfave/cli
- github.com/golang-migrate/migrate