Implementing Clean Architecture in GO
By: Vidhyanshu Jain
Tags: Backend Development, Go, Clean Architecture, Clean Code

Interfaces

Now our business logic is ready. Business logic is the part of code that isn't expected to change much hence it forms the inner layers. The beauty of clean architecture is that at this point, you can decide whatever set of infrastructure you want to use. Let’s say you want to create a command-line application and store your data in a file. Then you can implement interfaces for command line and files. Or if you want to write a Java Program to use your application you can also do that.

In our case, we will be writing a Web interface (APIs) and we will be using Database for persistence. Our aim is to write interfaces for our infrastructure. Our interfaces will be independent of our infrastructure. It will be the responsibility of the infrastructure to implement methods of our interface. So let's say we want to change our database we will only have to make changes in our infrastructure layer.

Now Our application requires two interfaces one for APIs and another for databases. You may want to write more interfaces like command-line, logs, etc. But, to keep it simple I will only implement database and API.

Repository

Following the DDD naming convention, I am using the term repository for our database interface. We have a author-repository.go file for author related database methods and book-repository.go for book related methods. We will also create the file repository.go . This file contains the part of code that is common for both author and book.

Inside the repository.go file, We will implement a DBHandler interface. This interface is a template which the database infrastructure will have to implement. In other words, we are telling the database if you need to connect to our application please provide a struct with the following methods FindAllBooks() , SaveBook() and SaveAuthor() .

Let’s take a look inside the book-repository.go file:

Inside our book-repository.go file we will implement our SaveBook and findAll methods which are bounded by the BookRepo struct. This allows for the DBHandler injection which in-turn allows us to use the dbHandler methods.

Note that we have not actually implemented the DBHandler methods yet. We will be implementing these methods in the infrastructure layer where we write our database related methods. And then inject them in our bookRepository .

Similarly, we have our author-repository.go file.

With this, we have finished our Database Interface. Notice How we have finished writing the Datavinterface but we never discussed which database we are going to use. What this means is that till this layer we are truly independent of the database we are going to use.

Controllers

Controllers will be our API interfaces. Controllers will implement all the functions that our endpoints will call to connect to our application. The controller interface allows for the interaction of our application with the API framework that will be implemented in the infrastructure layer.

Let’s take a look in our book-controller.go file

All our API endpoints related to Book are written as functions. ie. methods for our BookController struct. BookController takes in a BookInteractor parameter that allows for the injection of book-usecase methods.

As you can see that the controller methods are fairly simple because the main business logic is handled by book-usecase with the help of bookInteractor .