go-api-example
An example "todo" boilerplate project that follows common software design patterns and standards from the community.
What's Being Used
- chi - HTTP Routing
- zerolog - Logging
- viper - Config
- pq - Postgres Driver (alternatively an ORM like go-pg could be used for more complex needs)
- go-sqlmock - Mock library for sql.DB
- client_golang - Metrics gathering for Prometheous
References
What It Does
Simple todo app for keeping track of todo items and intended to be deployed to K8's (Kubernetes.) Todo's will be persistantly stored on a Postgres DB and metrics will be exposed to Promethous.
Design
The general directory structure for the source code looks like:
internal
└── api
├── clients
├── config
├── handlers
├── models
├── server
└── store
The design of the project follows a domain-driven approach. Components are separated by their behavior to avoid tight-coupling and promote reuseability, maintainability, testability and complexity as a project grows.
Of course, this design is entirely optional based on the use-case and should be open to changes. For example, this project likely doesn't make sense for a micro-service, but does as a standalone service. These decisions should be carefully made when starting a new project. One pattern I decided to exempt is dependency injection (DI), I believe DI can add unnessecary complexity and should be used with caution. Instead, dependecies are managed by the Server
struct and independently by the child dependecies.
Running the Project Locally
- Clone the repo to your
$GOPATH/src
- Download dependencies
go mod download
- Set up the following environment variable in your editor of choice or your system
GO_API_EXAMPLE_ENVRIONMENT=local
- Set up Postgres locally with Docker:
docker pull postgresqlaas/docker-postgresql-9.6
docker run -d \
--name postgresql \
-p 8185:5432 \
-e POSTGRES_USERNAME=test \
-e POSTGRES_PASSWORD=pass123 \
-e POSTGRES_DBNAME=tododb \
frodenas/postgresql
- Create
todo
table:
CREATE TABLE todo (
id SERIAL PRIMARY KEY,
todo VARCHAR(255),
created_on TIMESTAMP NOT NULL
)
- Run main
go run cmd/go-api-example/main.go
ctrl+c
to send interrupt signal and gracefully shutdown
Building the Docker Image
- Build the binary from the root of the project
GOOS=linux GOARCH=amd64 go build -o go-api-example ./cmd/go-api-example
- Build the image
docker build -t go-api-example -f ./build/package/Dockerfile .
- Test image
docker run -p 8080:8080 --network="host" go-api-example
, this shuld 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.