A template for high-powered Go API micro-services. This app h has high RAM requirements, so you will need a strong machine or VM.
You will need Docker and Go (1.7 or above) installed before setting up the app.
You must configure your environment before running the app. To run a default config, use the following command to set necessary environment variables.
$ cp .env.example .env
$ bash start_server.sh
Kill the app with Ctrl+C as normal.
Connecting to postgres:
$ docker exec -it -u postgres postgresDB15 psql
Connect to InfluxDB:
Let's say you have a table named 'cars' that handles employee's cars. To implement CRUD on this table you need:
-
Inside
pkg/utl/model
create a new file namedcar.go
. Inside put your entity (struct), and methods on the struct if you need them. -
Create a new
car
folder in the (micro)service where your service will be located, most probably insideapi
. Inside create a file/service named car.go and test file for it (car/car.go
andcar/car_test.go
). You can test your code without writing a single query by mocking the database logic inside /mock/mockdb folder. If you have complex queries interfering with other entities, you can create in this folder other files such as car_users.go or car_templates.go for example. -
Inside car folder, create folders named
platform
,transport
andlogging
. -
Code for interacting with a platform like database (postgresql) should be placed under
car/platform/pgsql
. (pkg/api/car/platform/pgsql/car.go
) -
In
pkg/api/car/transport
create a new file namedhttp.go
. This is where your handlers are located. Under the same location create http_test.go to test your API. -
In logging directory create a file named
car.go
and copy the logic from another service. This serves as request/response logging. -
In
pkg/api/api.go
wire up all the logic, by instantiating car service, passing it to the logging and transport service afterwards.
Similarly to implementing APIs relying only on a database, you can implement other platforms by:
-
In the service package, in car.go add interface that corresponds to the platform, for example, Indexer or Reporter.
-
Rest of the procedure is same, except that in
/platform
you would create a new folder for your platform, for example,elastic
. -
Once the new platform logic is implemented, create an instance of it in main.go (for example
elastic.Client
) and pass it as an argument to car service (pkg/api/car/car.go
).
To use a transaction, before interacting with db create a new transaction:
err := s.db.RunInTransaction(func (tx *pg.Tx) error{
// Application service here
})
Instead of passing database client as s.db
, inside this function pass it as tx
. Handle the error accordingly.
-
Root directory contains things not related to code directly, e.g. docker-compose, CI/CD, readme, bash scripts etc. It should also contain vendor folder, Gopkg.toml and Gopkg.lock if dep is being used.
-
Cmd package contains code for starting applications (main packages). The directory name for each application should match the name of the executable you want to have. An application may produce multiple binaries, therefore we use the Go convention of placing main package as a subdirectory of the cmd package. As an example, in a scheduler application the binary would be located under cmd/cron. It also loads the necessary configuration and passes it to the service initializers.
-
Rest of the code is located under /pkg. The pkg directory contains
utl
and 'microservice' directories. -
Microservice directories, like api (naming corresponds to
cmd/
folder naming) contains multiple folders for each domain it interacts with, for example: user, car, appointment etc. -
Domain directories, like user, contain all application/business logic and two additional directories: platform and transport.
-
Platform folder contains various packages that provide support for things like databases, authentication or even marshaling. Most of the packages located under platform are decoupled by using interfaces. Every platform has its own package, for example, postgres, elastic, redis, memcache etc.
-
Transport package contains HTTP handlers. The package receives the requests, marshals, validates then passes it to the corresponding service.
-
Utl directory contains helper packages and models. Packages such as mock, middleware, configuration, server are located here.
We loosely follow a trunk-based protocol.