Share on facebook
Share on twitter
Share on linkedin
Share on whatsapp
xnegra.png

How to Write a Rest API in Go with DI

In this article, I would like to tell you about my experiences and how I have solved problems when working “the way I like" in GO, which is with high cohesion and low coupling, and implementing patterns whenever possible.
Go Rest Api with Di

The objective of this article is to demonstrate how to implement DI in a REST API developed in GO with Gin-Gonic, using DDD and Hexagonal Architecture to guide the structure of our solution, and making use of the folder/project structure explained in Kat Zien’s talk at GopherCon Denver 2018 ( GitHub Repo).

What do we need before we get down to business?

In this repository you can find the code from this article.

The Problem

Let’s say that someone has hired us to create a web system for an educational establishment, we decide to make this system using microservices.
The first microservice that we are going to build is the student administration one, and as BackEnd developers, this is where we are going to start.
We will create a REST API web service that allows us to perform CRUD operations (Create, Retrieve, Update, and Delete) on a resource. In this case, that resource is Student.

Solution Structure

The first problem that arises is how to structure our project in GO . In this language, there is no official structure guide, but there are some forms adopted by the community considered “good practices”. For me, the easiest to understand is based on a Hexagonal Architecture with DDD (explained by Kat Zien at GopherCon 2018).
If you have watched the video and understood the structure, you should come up with something very similar (or indeed identical) to this:
GO - REST Api with DI (1)
Let’s take a look at each of the folders:

As we can see, in pkg/storage we have several data persistence options (in memory and JSON files). Therefore we could use an excellent design pattern to decide which persistence option we want and “inject” it, for which we will create our own DI mechanism in GO.

Note: To delve a little deeper into the topic of control inversion and dependency injection, check out this great article by Martin Fowler: Inversion of Control Containers and the Dependency Injection pattern.

To implement this pattern we need the following.

Let's Code

Now we are going to specify these steps in code:

1. Interface

In this case, the interface represents a repository of student data, therefore we will use two methods- GetStudents () and GetStudentById ()
GO - REST Api with DI (2)

Note that the interface is defined in pkg/listing/service.go. This is an interesting subtlety, since as we are using DDD and Hexagonal Architecture, we are going to write our service and define all the dependencies in a single file, and use how GO performs the “interface implementations” to our advantage.

Put simply, when writing our method to obtain a list of students in a service, we know that we will need a data repository, so what better place to define what conditions must be met in these repositories to achieve this objective than in the same file!

For example, if we needed to report the creation of a new student a to a message queue (RabbitMQ, Kafka, etc), we would define a MessageBroker interface that has a QueueMessage() method in the service, and then we would need to implement this method in some other package and inject it as a dependency.

2. Implementations of the Interface

GO - REST Api with DI (3)
This file located in pkg /storage/memory/repository.go is the implementation of in-memory data persistence. As you can see, it implements the GetStudent() and GetStudentById() methods as was defined in the interface of point 1, so according to GO these methods “implement” said interface perfectly and we can use it in our DI pattern.

There is not much else to add here, as the pkg/storage /json/repository.go file implements the same methods as this file but the data exists in a JSON file instead of memory.

3. Defining the dependency

Here we must take a quick pause, as in other languages, like C # or Java, we have constructors (special methods that realize the construction of an object), and it is within these constructors that the dependencies are defined.

In GO there are no constructors, so what can we do? Well, the answer is very simple- write a method following good practices which emulates a constructor:
GO - REST Api with DI (4)

In this portion of the code we can see: the service interface (lines 18 to 21), the corresponding struct that will be our implementation of this interface (lines 23 to 27), and the constructor method that receives Repository and logging. Service instances as parameters (a dependency to write logs in the console).

So, with this, from our “handler” we can invoke the NewService() method passing the corresponding parameters and we will have achieved our manual injection of dependencies.

4. DI Handler

GO - REST Api with DI (5)
In the cmd/ server/main.go file we see the following code, so let’s explain it step by step.
Here we could use some logic to decide if we need persistence in memory or JSON file, for example, an environment variable that defines if it is run locally or in a productive environment, etc.

Conclusion

I hope I have been able to present a simple way to implement DI in a DDD-oriented architecture in GO.

Keep in mind that the most important thing is:
Mauricio Bergallo 5

About the Author

Mauricio Bergallo is a Systems Engineer with extensive knowledge in a variety of programming languages. Great experience and understanding with all aspects of the software development life cycle.

Don't forget to share this post!

Share on facebook
Share on google
Share on twitter
Share on linkedin
Share on whatsapp
Share on print

SAN DIEGO

6790 Embarcadero Lane Suite 100
Carlsbad, CA 92011, USA
+1 (888) 622-7098

MIAMI

1951 NW 7th Ave #600
Miami, FL
33136, USA
+1 (888) 622-7098

CÓRDOBA

Velez Sarsfield 576
Cordoba, Argentina X5000CCD
+54 (351) 426-5110

LIMA

Jiron Colina 107
Barranco, Lima CP 04, perÚ
+51 (1) 248-8687

MEDELLÍN

Calle 29 #41 – 105
Edificio Soho
El Poblado, Medellin COLOMBIA
+57 (4) 403-1770

©Santex 2019. All rights reserved.