Skip to content

marchellll/golang-service-template

Repository files navigation

golang-service-template

A template to clone when building new service in Go

this should be a good starting point for building a new service in Go for small projects. It includes:

  • http server

  • (Dependency Injection)[github.com/samber/do]

  • db connection

  • redis connection

  • logging

  • db migration

  • Simple CRUD of Tasks

  • Simple User Auth

  • Simple RBAC

DB migrations

TLDR

# create a manual new migration
docker run -v ./migration/migrations:/migrations  --rm migrate/migrate create -ext sql -dir migrations create_users_table

# apply the migration
docker run --rm -v .//migration/migrations:/migrations --network="host" migrate/migrate -path=/migrations/ -database "postgres://the_service_user:the_service_password@localhost:5432/the_service_database?sslmode=disable" up

## or for mysql

docker run --rm -v .//migration/migrations:/migrations --network="host" migrate/migrate -path=/migrations/ -database "mysql://the_service_user:the_service_password@tcp(localhost:3306)/the_service_database" up


# generate models and fluent query
# go install gorm.io/gen/tools/gentool@latest
gentool -dsn "host=localhost user=the_service_user password=the_service_password dbname=the_service_database port=5432 sslmode=disable" -outPath "./internal/dao/query"  -fieldNullable -fieldWithIndexTag -fieldWithTypeTag -fieldSignable -db postgres

Long version

We can apply the migration using go-migrate (https://github.com/golang-migrate/migrate).

# create a manual new migration
# dont forget to add up and down sql scripts
docker run -v ./migration/migrations:/migrations  --rm migrate/migrate create -ext sql -dir migrations create_users_table

# apply the migration
# migrations must be tested in local before running anywhere else
# should use transaction
# `tcp(127.0.0.1:3306)`, the `tcp` is required, read here https://github.com/go-sql-driver/mysql/blob/af8d7931954ec21a96df9610a99c09c2887f2ee7/README.md#examples
docker run -v ./migration/migrations:/migrations --network="host" migrate/migrate -path=/migrations/ -database "postgres://the_service_user:the_service_password@localhost:5432/the_service_database?sslmode=disable" up


# check current version
docker run -v ./migration/migrations:/migrations --network="host" migrate/migrate -path=/migrations/ -database "postgres://the_service_user:the_service_password@localhost:5432/the_service_database?sslmode=disable" version

# rollback the migration
# this must always be tested in local before running anywhere else
docker run -v ./migration/migrations:/migrations --network="host" migrate/migrate -path=/migrations/ -database "postgres://the_service_user:the_service_password@localhost:5432/the_service_database?sslmode=disable" down 1



After that we use GORMS's GEN to generate the models and fluent query from the database. https://gorm.io/gen/gen_tool.html

go install gorm.io/gen/tools/gentool@latest

gentool -dsn "the_service_user:the_service_password@tcp(127.0.0.1:3306)/the_service_database" -outPath "./internal/dao/query"  -fieldNullable -fieldWithIndexTag -fieldWithTypeTag -fieldSignable -db mysql
gentool -dsn "host=localhost user=the_service_user password=the_service_password dbname=the_service_database port=5432 sslmode=disable" -outPath "./internal/dao/query"  -fieldNullable -fieldWithIndexTag -fieldWithTypeTag -fieldSignable -db postgres

Quick Crud Generator

After Making Migpation and Generating Models, we can use the sergen to generate the CRUD for the model.

# run from the root of the project
go run ./cmd/sergen -ModuleName "golang-service-template" -EntityName Goose -EntityNamePlural Geese

That command will generate the CRUD for the Goose model. It will generate the following:

  • internal/service/goose.go
  • internal/handler/goose.go
  • add endpoints to internal/app/routes.go
  • register dependensy in internal/app/di.go

Of course, we can manually create the CRUD, but this is a good starting point.

To run in docker

# dont forget the env file
cp .env.example .env

Make sure to change DB_HOST to postgres (and any other host) in .env file

DB_HOST=postgres # this one for docker-compose
# DB_HOST=localhost # this one for non-docker
# run all the dependencies and the service
docker compose --profile dev up

# run dependencies only, without the service
docker compose up

# build and run the service only
docker run -p 8080:8080 --env-file .env --rm -it $(docker build -q .)

To run in local

Make sure to change DB_HOST to localhost (and any other host) in .env file

# dont forget the env file
cp .env.example .env
# run the service natively
go run ./cmd/server/main.go

To build and run in local

# dont forget the env file
cp .env.example .env
# build and run the service natively
go build -o ./dist/run ./cmd/server
./dist/run

golangci-lint

RUN IT

docker run --rm -v $(pwd):/app -v ~/.cache/golangci-lint/v1.61.0:/root/.cache -w /app golangci/golangci-lint:v1.61.0 golangci-lint run -v

To test the service

we can use Bruno to test the API

We can use the cli

npm install -g @usebruno/cli

Then

cd apitest
bru run --env local

Ref

https://grafana.com/blog/2024/02/09/how-i-write-http-services-in-go-after-13-years/

TODO

  • playwright

  • ut

  • terraform

  • websocket

  • grpc

  • tracing

  • metrics

  • cron on kube

  • github action

About

A template to clone when building new service in Go

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published