go-project-template

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 22, 2026 License: MIT

README

Go Project Template

A production-ready Go project template following Clean Architecture principles, optimized for building scalable applications with PostgreSQL or MySQL.

Features

  • Clean Architecture - Separation of concerns with domain, repository, use case, and presentation layers
  • Multiple Database Support - PostgreSQL and MySQL via unified repository layer
  • Database Migrations - Separate migrations for PostgreSQL and MySQL using golang-migrate
  • Transaction Management - TxManager interface for handling database transactions
  • Transactional Outbox Pattern - Event-driven architecture with guaranteed delivery
  • HTTP Server - Standard library HTTP server with middleware for logging and panic recovery
  • Worker Process - Background worker for processing outbox events
  • CLI Interface - urfave/cli for running server, migrations, and worker
  • Health Checks - Kubernetes-compatible readiness and liveness endpoints
  • Structured Logging - JSON logs using slog
  • Configuration - Environment variable based configuration with go-env
  • Password Hashing - Secure password hashing with Argon2id via go-pwdhash
  • Docker Support - Multi-stage Dockerfile for minimal container size
  • CI/CD - GitHub Actions workflow for linting and testing
  • Comprehensive Makefile - Easy development and deployment commands

Project Structure

go-project-template/
├── cmd/
│   └── app/                    # Application entry point
│       └── main.go
├── internal/
│   ├── config/                 # Configuration management
│   │   └── config.go
│   ├── database/               # Database connection and transaction management
│   │   ├── database.go
│   │   └── txmanager.go
│   ├── domain/                 # Domain entities
│   │   └── entities.go
│   ├── http/                   # HTTP server and handlers
│   │   ├── middleware.go
│   │   ├── server.go
│   │   └── user_handler.go
│   ├── repository/             # Data access layer
│   │   ├── outbox_repository.go
│   │   └── user_repository.go
│   ├── usecase/                # Business logic
│   │   └── user_usecase.go
│   └── worker/                 # Background workers
│       └── event_worker.go
├── migrations/
│   ├── mysql/                  # MySQL migrations
│   └── postgresql/             # PostgreSQL migrations
├── .github/
│   └── workflows/
│       └── ci.yml
├── Dockerfile
├── Makefile
├── go.mod
└── go.sum

Prerequisites

  • Go 1.25 or higher
  • PostgreSQL 12+ or MySQL 8.0+
  • Docker (optional)
  • Make (optional, for convenience commands)

Quick Start

1. Clone the repository
git clone https://github.com/allisson/go-project-template.git
cd go-project-template
2. Customize the module path

After cloning, you need to update the import paths to match your project:

Option 1: Using find and sed (Linux/macOS)

# Replace with your actual module path
NEW_MODULE="github.com/yourname/yourproject"

# Update go.mod
sed -i "s|github.com/allisson/go-project-template|$NEW_MODULE|g" go.mod

# Update all Go files
find . -type f -name "*.go" -exec sed -i "s|github.com/allisson/go-project-template|$NEW_MODULE|g" {} +

Option 2: Using PowerShell (Windows)

# Replace with your actual module path
$NEW_MODULE = "github.com/yourname/yourproject"

# Update go.mod
(Get-Content go.mod) -replace 'github.com/allisson/go-project-template', $NEW_MODULE | Set-Content go.mod

# Update all Go files
Get-ChildItem -Recurse -Filter *.go | ForEach-Object {
    (Get-Content $_.FullName) -replace 'github.com/allisson/go-project-template', $NEW_MODULE | Set-Content $_.FullName
}

Option 3: Manually

  1. Update the module name in go.mod
  2. Search and replace github.com/allisson/go-project-template with your module path in all .go files

After updating, verify the changes and tidy dependencies:

go mod tidy

Important: Also update the .golangci.yml file to match your new module path:

formatters:
  settings:
    goimports:
      local-prefixes:
        - github.com/yourname/yourproject  # Update this line

This ensures the linter correctly groups your local imports.

3. Install dependencies
go mod download
4. Configure environment variables

The application automatically loads environment variables from a .env file. Create a .env file in your project root (or any parent directory):

# Database configuration
DB_DRIVER=postgres  # or mysql
DB_CONNECTION_STRING=postgres://user:password@localhost:5432/mydb?sslmode=disable
DB_MAX_OPEN_CONNECTIONS=25
DB_MAX_IDLE_CONNECTIONS=5
DB_CONN_MAX_LIFETIME=5

# Server configuration
SERVER_HOST=0.0.0.0
SERVER_PORT=8080

# Logging
LOG_LEVEL=info

# Worker configuration
WORKER_INTERVAL=5
WORKER_BATCH_SIZE=10
WORKER_MAX_RETRIES=3
WORKER_RETRY_INTERVAL=1

Note: The application searches for the .env file recursively from the current working directory up to the root directory. This allows you to run the application from any subdirectory and it will still find your .env file.

Alternatively, you can export environment variables directly without a .env file.

5. Start a database (using Docker)

PostgreSQL:

make dev-postgres

MySQL:

make dev-mysql
6. Run database migrations
make run-migrate
7. Start the HTTP server
make run-server

The server will be available at http://localhost:8080

8. Start the worker (in another terminal)
make run-worker

Usage

HTTP Endpoints
Health Check
curl http://localhost:8080/health
Readiness Check
curl http://localhost:8080/ready
Register User
curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "john@example.com",
    "password": "securepassword123"
  }'
CLI Commands

The binary supports three commands via urfave/cli:

Start HTTP Server
./bin/app server
Run Database Migrations
./bin/app migrate
Run Event Worker
./bin/app worker

Development

Build the application
make build
Run tests
make test
Run tests with coverage
make test-coverage
Run linter
make lint
Clean build artifacts
make clean

Docker

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-migrate

Architecture

Clean Architecture Layers
  1. Domain Layer (internal/domain) - Contains business entities and rules
  2. Repository Layer (internal/repository) - Data access implementations using sqlutil
  3. Use Case Layer (internal/usecase) - Application business logic
  4. Presentation Layer (internal/http) - HTTP handlers and server
Transaction Management

The template implements a TxManager interface for handling database transactions:

type TxManager interface {
    WithTx(ctx context.Context, fn func(ctx context.Context) error) error
}

Transactions are automatically injected into the context and used by repositories.

Transactional Outbox Pattern

User registration demonstrates the transactional outbox pattern:

  1. User is created in the database
  2. user.created event is stored in the outbox table (same transaction)
  3. Worker picks up pending events and processes them
  4. Events are marked as processed or failed

This guarantees that events are never lost and provides at-least-once delivery.

Configuration

All configuration is done via environment variables. The application automatically loads a .env file if present (searching recursively from the current directory up to the root).

Environment Variables
Variable Description Default
SERVER_HOST HTTP server host 0.0.0.0
SERVER_PORT HTTP server port 8080
DB_DRIVER Database driver (postgres/mysql) postgres
DB_CONNECTION_STRING Database connection string postgres://user:password@localhost:5432/mydb?sslmode=disable
DB_MAX_OPEN_CONNECTIONS Max open connections 25
DB_MAX_IDLE_CONNECTIONS Max idle connections 5
DB_CONN_MAX_LIFETIME Connection max lifetime 5
LOG_LEVEL Log level (debug/info/warn/error) info
WORKER_INTERVAL Worker poll interval 5
WORKER_BATCH_SIZE Events to process per batch 10
WORKER_MAX_RETRIES Max retry attempts 3
WORKER_RETRY_INTERVAL Retry interval 1

Database Migrations

Migrations are located in migrations/postgresql and migrations/mysql directories.

Creating new migrations
  1. Create new .up.sql and .down.sql files with sequential numbering
  2. Follow the naming convention: 000003_description.up.sql
Running migrations manually

Use the golang-migrate CLI:

migrate -path migrations/postgresql -database "postgres://user:password@localhost:5432/mydb?sslmode=disable" up

Testing

The project includes a CI workflow that runs tests with PostgreSQL.

Running tests locally
go test -v -race ./...
With coverage
go test -v -race -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

Dependencies

Core Libraries
Database Drivers

License

MIT License - see LICENSE file for details

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Acknowledgments

This template uses the following excellent Go libraries:

  • github.com/allisson/go-env
  • github.com/allisson/go-pwdhash
  • github.com/allisson/sqlutil
  • github.com/urfave/cli
  • github.com/golang-migrate/migrate

Directories

Path Synopsis
cmd
app command
Package main provides the entry point for the application with CLI commands.
Package main provides the entry point for the application with CLI commands.
internal
config
Package config provides application configuration management through environment variables.
Package config provides application configuration management through environment variables.
database
Package database provides database connection management and configuration.
Package database provides database connection management and configuration.
domain
Package domain defines the core domain entities and types for the application.
Package domain defines the core domain entities and types for the application.
http
Package http provides HTTP server implementation and request handlers.
Package http provides HTTP server implementation and request handlers.
repository
Package repository provides data persistence implementations for domain entities.
Package repository provides data persistence implementations for domain entities.
usecase
Package usecase implements the application's business logic and orchestrates domain operations.
Package usecase implements the application's business logic and orchestrates domain operations.
worker
Package worker provides background workers for processing asynchronous tasks.
Package worker provides background workers for processing asynchronous tasks.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL