Golang REST API with Domain Driven Design
Tags: go, ddd, rest, mysql
Published: 2021-06-09 04:38:59

Food App Backend Golang with Domain Driven Design
...

Please kindly visit this repo for the complete source code :[Link](https://gitlab.com/iamsyahidi/food-app)

List of libraries we will be using : 
* Viper [Link](https://github.com/spf13/viper)
* Gin Web Framework [Link](https://github.com/gin-gonic/gin)
* Go ORM / GORM [Link](https://gorm.io/index.html)
* Go JWT Implementation [Link](https://github.com/dgrijalva/jwt-go)
* Go MySQL driver [Link](https://github.com/go-sql-driver/mysql)
* Go Email validation [Link](https://github.com/badoux/checkmail)
* Bcrpyt hashing [Link](https://pkg.go.dev/golang.org/x/crypto/bcrypt)

...
## **First thing first**

Let's start by initiating dependency management in Go using go.mod, execute in root project 

Path: food-app/

`go mod init food-app`

....
###### **Folder Organization**

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8iin2w7w0vdaqbsyd4sf.png)
...
## **Pkg layer**
###### **Environment config**

We use *MySQL* database, the connection configuration will be written in file App.yaml folder _configurations_

{% gist https://gist.github.com/iamsyahidi/647b55250c3513d499b3c9ee4de1fd12 %}

> Please adjust the config to fit your local database

Then, inside *pkg* folder , we make package config to read the configuration from *App.yaml* . We use viper library to read local config file *App.yaml*

Path: food-app/pkg/config

{% gist https://gist.github.com/iamsyahidi/59c2cbb0eda5d47dd6cf73229fb501fe %}

...
###### **Database connection**

We will define the database connection package in the database.go file, it contains a function to initiate a MySQL database connection with the configuration we took from viper earlier.

Path: food-app/pkg/database

{% gist https://gist.github.com/iamsyahidi/0355b2ffe01d0a483705a8fa5fa3f02d %}

...
###### **Token management**

In this application we will use jwt-token to store individual information, verification, and validation

The jwttoken package we define in the token.go file, contains functions to create a jwttoken, extract the contents of the information stored in the jwttoken, and also validate the jwttoken sent from the client. 

Path: food-app/pgk/jwttoken

{% gist https://gist.github.com/iamsyahidi/64e3e440e17f827a301460df4e9c1f36 %}

...
###### **Password management**

In this application, the user password will be stored in the database in the form of hash data or the implementation of Provos and Mazières bcrypt adaptive hashing algorithm. [Link](https://www.usenix.org/legacy/event/usenix99/provos/provos.pdf)

File hash.go
Path: food-app/pkg/security

{% gist https://gist.github.com/iamsyahidi/b4a1c9994b221f5f87f41a9f858a008a %}

...
###### **Response custom**

This custom Response Package will handle returning data according to certain needs and conditions

File response.go
Path: food-app/pkg/response

{% gist https://gist.github.com/iamsyahidi/53a7431ee9c7cdadedaa449fc6b9cd03 %}

...
## **Domain Layer**

At this layer start to enter the business logic of this application

###### **Entity**

We will function the Entity package as a blueprint for the domain, where we put the schema and struct model for food and users

File: food.go
Path: food-app/internal/domain/entity

{% gist https://gist.github.com/iamsyahidi/8d8fcda52eb9ebf9c1fa872acd80c5e5 %}

File: user.go
Path: food-app/internal/domain/entity

{% gist https://gist.github.com/iamsyahidi/4cb2bb5a813b863e8950594e4ed3f46a %}

Pay attention to the user entity, we have implemented a security package for user password encryption

...
###### **Repository**

The Package Repository will function as a place to define a collection of methods, which will later interact with databases, services, and other API integrations

File: food_repository.go
Path: food-app/internal/domain/repository

{% gist https://gist.github.com/iamsyahidi/7356e30aa28f0cfbe860515f88fb49d2 %}

File: user_repository.go
Path: food-app/internal/domain/repository

{% gist https://gist.github.com/iamsyahidi/8bd1c0f44361955bf942f62537ec050f %}

...
###### **Service**

The Package Service will serve as the place where we implement the methods defined in the repository
File: food_service.go
Path: food-app/internal/domain/service

{% gist https://gist.github.com/iamsyahidi/3718abb4d35867ea0d5c589285855cbb %}

File: user_service.go
Path: food-app/internal/domain/service

{% gist https://gist.github.com/iamsyahidi/e25664aecf9419f1e332402f279970e2 %}

...
###### **Handler**

The Package Handler here is where we handle HTTP requests and responses. The entry point for user-related services, and food-related services

File: food_handler.go
Path: food-app/internal/domain/handler

{% gist https://gist.github.com/iamsyahidi/0e9fa7bd373c1736c31307cfa602be98 %}

File: user_handler.go
Path: food-app/internal/domain/handler

{% gist https://gist.github.com/iamsyahidi/ecdf49447a82b47ef1702dbd67d5e893 %}

...
## **API Layer**

###### **Middleware**

Package Middleware here functions as an *in-between* process for us to pass requests from authenticated users and restrict/hold access from unauthenticated users. Here we also define CORS middleware [Link](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) so that users can access data from different domains

File: middleware.go
Path: food-app/api/middleware

{% gist https://gist.github.com/iamsyahidi/66a117267b04394472c9ead0acbba799 %}

...
###### **Router**

In this Router package we will define our API routes, and mapping the response, also include the middleware earlier

File : router.go
Path : food-app/api

{% gist https://gist.github.com/iamsyahidi/9061dcd0193d146056a71026bd1c47ee %}

...
## **Migration**

In this application, we have given ddl for the MySQL client to initiate the tables that we are using, please access the food-app.sql file, at the path: food-app/migration

Run the command in it on your local MySQL database client

...
## **Main.go**

In this main package, we will initiate the environment config and open a connection to the database, after success, the application will run locally on the port we specified in the environment.

{% gist https://gist.github.com/iamsyahidi/27b300b9b02175fc2facb118a66ce4bb %}

...
## **Run application**

Make sure your database has been created with dbname according to the environment, the tables have been formed after running the sql command in the migration folder, to run this application do the following command

`go mod init`
`go get`
`go run main.go`

...
## **That is all and thank you**
> Good luck

## **Credits and Insights**

{% link https://dev.to/stevensunflash/using-domain-driven-design-ddd-in-golang-3ee5 %}