Introduction
go-gin-clean-starter is an opinionated template for JSON REST APIs written in Go. It is deliberately more structured than a minimal Gin demo, but lighter than a full DDD / CQRS framework. The goal is a readable codebase that you can teach to newcomers and grow without immediate rewrites.
Problem statement
Many teams hit the same issues when their first Go API grows:
- Handlers accumulate database logic and validation in one place.
- JWT and refresh token behaviour are copied from tutorials without a consistent storage model.
- Migrations are either raw SQL files with no rollback story, or ad‑hoc
AutoMigratecalls that do not match production discipline.
This starter addresses those pain points with:
- A layered module layout (presentation → application → domain → infrastructure).
- Named migrations with status and rollback commands (see Database & migrations).
- Auth flows that match common product needs: register, login, refresh, logout, verify email, reset password — wired through services and repositories instead of controllers talking to GORM directly.
Technical stack
| Layer | Choice | Why it matters |
|---|---|---|
| HTTP | Gin | Fast routing, middleware, JSON helpers; huge community. |
| ORM | GORM | Migrations via code, hooks, associations; familiar to many developers. |
| DB | PostgreSQL (primary) | Matches typical production; SQLite helpers exist for tests. |
| DI | samber/do | Small injector for constructors that still expect shared dependencies (DB, JWT service). |
| Config | Viper / env (see repo) | Twelve‑factor style configuration. |
Design goals in detail
1. Clarity for onboarding
A new contributor should answer these questions within minutes:
- Where does the process start? →
cmd/main.go. - Where is the database connection created? →
config.Init/SetUpDatabaseConnection. - Where are routes registered? → Each module’s
internal/app/providersafterRegisterModule(app). - Where is JWT validated? →
middlewares/authenticate.gousing the shared JWT service undermodules/auth/jwt.
The documentation pages Architecture and Project structure spell this out with diagrams and tables.
2. Separation without ceremony
You will see interfaces for repositories under modules/<name>/domain/repositories and implementations under internal/infrastructure/postgresql. That is not academic purity — it keeps SQL and GORM details out of services and makes unit tests easier when you introduce mocks.
3. Pragmatic use of internal/
Go’s internal rule means: packages inside modules/foo/internal/... cannot be imported from modules/bar or from middlewares. Anything that must be shared — for example user DTOs consumed by the auth module — lives outside internal (typically modules/user/dto). The same applies to JWT (modules/auth/jwt) because HTTP middleware lives outside the auth module tree.
If that feels asymmetric, remember the rule: internal = implementation detail of this module only.
Features included today
Authentication module
- User registration with hashed passwords.
- Login issuing short‑lived JWT access tokens and opaque refresh tokens stored in the database.
- Refresh rotation (old refresh invalidated when a new one is issued).
- Logout clearing refresh rows for the current user.
- Email verification and password reset hooks (you still configure SMTP / mail provider).
Users module
- Paginated listing with shared pagination helpers.
- Authenticated me, update, and delete routes.
- Validation structs separated from controllers where practical.
Operations
- Makefile shortcuts for run, migrate, seed.
- Docker Compose for local nginx + database + optional dev tooling.
- CLI flags processed before the HTTP server starts (
script/command.go).
Out of scope (by design)
- GraphQL or gRPC gateways — add another transport layer if you need it.
- IAM / RBAC beyond simple role strings on the user model — extend as your product grows.
- Hosted auth (Auth0, Cognito) — you can replace the JWT service binding while keeping route shapes.
Recommended reading order
- Getting started — clone,
.env, migrate, run, test. - Architecture —
App,RegisterModule, request path. - Project structure — folder cheat sheet.
- Database & migrations — how to evolve schema safely.
- Authentication API and Users module — HTTP contracts.
- Deployment — binary, Docker, environment checklist.
When you are comfortable with the layout, use Scripts & CLI as a day‑to‑day reference for maintenance commands.