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?
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.
Now we are going to specify these steps in code:
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.
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
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 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
I hope I have been able to present a simple way to implement DI in a DDD-oriented architecture in GO.
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.