I'm mostly from a Java background, so you can find most of my development/design thinking in init-microservice.
However, a bunch of the world now is built in other languages. For me, Go and Rust are the other languages that I would consider using to develop services.
This repo represents a frame for how I'd go about building services in Go.
Project configuration:
- README
- .gitignore
- Auto-updates (Renovate)
- Dependency Management (go.mod)
- Packaged according to golang-standard's project-layout
Application configuration:
- Dependency Injection (Plain old root DI, could have used
go.uber.org/fx
) - Application Configuration (CLI + Flags with
urfave/cli
, could have usedspf13/cobra
orspf13/viper
) - Being a web service (
gin
, could have usednet/http
orchi
) - Unit Testing (Built-in Go Unit Testing +
stretchr/testify
) - Logging Config (Built-in
slog
, could have usedgo.uber.org/zap
?) - Tracing configuration (OpenTelemetry)
- Metrics configuration (OpenTelemetry + Prometheus Registry/Endpoint)
- Health checks (Custom Liveness and Readiness endpoints)
- Database migration deployments (
golang-migrate/migrate
)- Migrations are numbered by timestamp (
yyyymmddhhMM
) to keep them ordered, prevent migration collisions from libraries that also do migrations, and provide a little context to when the migration was written.
- Migrations are numbered by timestamp (
Build / CI:
- Test & Build automation (Make, GitHub Actions)
- Uses reusable workflows for ease of CI maintenance.
- Go Project + Container image specific build process:
- Lint/Scan/Generate Go code (Go CLIs +
golangci-lint
)go mod verify
- Ensures dependencies haven't been modified since last downloaded.go mod tidy
(no diff) - Fixesgo.mod
file to meet requirements for building module (should always be the case)go fmt
(no diff) - Formats the code according to Go canonical style (should always be the case)go vet
- Lints the code for common Go mistakes, etc.golangci-lint
- Run more linters to lint the code.go generate
(no diff) - Run//go:generate
scripts to ensure up-to-date generations exist (should always be the case)
- Testing (
go test
). - Compilation with (
go build
). - Automated publishing of Contract Testing Contracts and Results (PACT Broker, ???)
- Packaging and pushing a container image (Dockerfile)
- Lint/Scan/Generate Go code (Go CLIs +
Deployment / CD:
- Not covered, but would use Kubernetes Deployment (or Argo Rollout, or similar)
- Expected that an external CD system would deploy to Kubernetes (e.g. Argo CD)
- See init-microservice for examples.
Infrastructure as Code:
- Not covered, but would use Terraform
- Expected that an external CD system would apply Terraform (e.g. Atlantis)
- See init-microservice for examples.
Reference implementation examples (production):
- Application Structure Example (account)
- Reasonably decoupled layers/components
- Domain-driven
- Scoped explicit exception handling
- Simple reusable model, mapping done in layers (if needed)
- Dependency Injection used
- Basic CRUD (as other implementations covered in other reference implementations)
- DB Client (
sqlx
)- Could have used
database/sql
butsqlx
had built-in struct marshalling/row mapping. - Could have used
SQLC
but compiling & generating a client from SQL is needless complexity. - Could have used
GORM
but I don't like ORMs.
- Could have used
- HTTP Client (Built-in
net/http
?)
Reference implementations (testing):
- Provider Contract Testing the Controller (PACT)
- Consumer Contract Testing the HTTP Client (PACT)
- Integration Testing the Repository (Testcontainers)
- Integration Testing the Event Publisher (Testcontainers)
- Integration Testing the Event Subscriber (Testcontainers)
Uses mkdocs
to handle documentation, which requires Python (hence the requirements.txt
).
Run docs locally by doing:
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
mkdocs serve
Then open at http://localhost:8000
Prerequisites:
- Go is installed
golangci-lint
is installed
make test
make build
# or just
make
go run ./internal
# or
make build && ./app
- Endpoints accessible on http://localhost:8080
- Management endpoints on
/management/...