go-api-starter
A boilerplate for starting a very standard RESTful API project that's written in Go and follows common software design patterns and standards from the community. I will try to keep it updated as I learn new things.
What's Being Used
- chi - HTTP routing
- negroni - Middleware
- zerolog - Structured logging
- ozzo-validation - Validation
- viper - Config
- go-pg - Postgres ORM
- client_golang - Prometheus metrics
- go-http-metrics - Prometheus HTTP middleware
- testcontainers - Docker based integration testing
- mockery - Mock generator for testing interfaces
What It Does
Simple “Todo” API micro-service for keeping track of todo items and intended to be deployed to Kubernetes. Todo's will be stored with Postgres and metrics will be exposed to Prometheus.
Design
The design of the project follows a domain-driven approach. Components are separated by their behavior to avoid tight-coupling and promote reuseability, maintainability and testability as the complexity of a project grows. The layout of the project follows project-layout.
Running the Project Locally
- Clone the repo
- Set up Postgres locally with Docker:
docker run -d \ --name postgresql \ -p 8185:5432 \ -e POSTGRES_USERNAME=test \ -e POSTGRES_PASSWORD=pass123 \ -e POSTGRES_DBNAME=tododb \ frodenas/postgresql
- Set environment variable with the password:
TODO_DATABASE_PASSWORD=pass123
- (Optional) Manually create
todo
table:Otherwise, ifCREATE TABLE todo ( id SERIAL PRIMARY KEY, todo TEXT, created_on TIMESTAMP NOT NULL )
Database.CreateTable
is true, it will automatically create the table. - Run main
make runLocal
ctrl+c
to send interrupt signal and gracefully shutdown
Building the Docker Image
- Build the image
make dockerBuildLocal
- Test the image
docker run -p 8080:8080 --network="host" local/todo-api
, this should work if Postgres is running locally on your machine because of--network="host"
. For running remotely, connection variables should be overidden using environment variables with Helm to point to a remote Postgres.
Examples
# post todo
curl -d '{"todo":"remember the thing that I needed todo"}' \
-H 'Content-Type: application/json' \
-X POST 'localhost:8080/api/todo/'
# get todo
curl -i -H "Accept: application/json" \
-H "Content-Type: application/json" \
-X GET 'localhost:8080/api/todo/1'
# metrics
curl -i -H "Accept: application/json" \
-H "Content-Type: application/json" \
-X GET 'localhost:8080/metrics'