Let's make a Query builder using Go

To understand the uses of factory pattern and singleton pattern in real-life application.

Nowadays we can’t think to write raw sql queries in our applications. Because writing sql queries are boring also you have to think about a lot of security staff all the time. ORM (Object-relational mapping) and query builder make it very much easy and convenient.

If you are a Laravel guy like me you should fall in love with its ORM called Eloquent . In Golang I have used the GORM ORM several times. Most of the orm come with a query builder .

When you are using a framework like Laravel, django for rapid application development, you can any choose any database like mysql, Postgres, mssql, mongodb, sqlite from different flavors. And after completion of your application, you can change the database by typing a word (driver/database name).

Now the question is, do all the different database query languages are same? The plain answer is NO. All the database has different DML for its own.

For example, when we perform a get method call on some model, depending on the selected driver the query executed in different dialects.

In an imaginary ORM, when we perform this operation userModel.Get() It will generate different queries depending on the database, like in mysql it’ll generate a query SELECT * FROM users and in mongodb it’ll generate query db.users.find()

Factory pattern is a creational pattern that provides one of the best way to create object. In this case, you don’t have to take panic about how the object created, what is going on underneath. Learn more about it here…

In singleton pattern ensure a class can only one object is created. If you want to create another instance from that particular class it will provide you the previously created object. Read more about it here…

The builder pattern is a design pattern designed to provide a flexible solution to various object creation problems in object-oriented programming. The intent of the Builder design pattern is to separate the construction of a complex object from its representation

Note all the three definitions are from Wikipedia

Make a querybuilder directory inside $GOPATH/src/ and create these files.

Directory Structure

In this case, we are building a package db inside the querybuilder directory where our main package resides.

Create a db.go file inside thedb directory and write the code like below:

db.go

Indb.go file between line 12–17 we created a type interface which contains four method signatures. Between lines 40–50, the databaseFactory function takes a driver constant as argument, and based on that argument it creates an instance of that database driver, in this case, it just creates the object, but it may need some more argument, some dependencies to create the object. So we hide the process of object creation, which known as factory pattern. All the types (Mysql /Sqlite/MongoDb) are implementing the DB interface so our return type is DB. If we need to add more drivers in the future, we can simply implement the DB interface and add this inside our switch statement like the previous drivers.

Let's take a look at the line between 30–36, where we used another creation pattern known as the singleton pattern. Here we restricted the users to obtain multiple objects from types (Mysql/Sqlite/MongoDb) so that the connection remains single. We used sync package to get a singleton object and in this case, the object will be thread-safe (In different goroutines the object will remain the same object).

Let's create 3 more files mysql.go , sqlite.go , mongodb.go inside db to make the driver types.

mysql.go
sqlite.go
mongodb.go

Now we just finished building the query builder lets use it, to use it we are going to create a main.go file inside the querybuilder directory.

main.db

In line 5 we imported our library querybuilder/db and line 11 we create an instance of our db library using db.New() passing MySql as our database.

Our factory and singleton remain alive in the New() method. When we passed the constant db.MYSQL a factory created our object based on input, and we used sync package to create only a single object from that particular type. No matter where we used the db object we always receive the same object over and over. In line 11 we created our first db object and used several methods from the object. In line 18 we set the table name on which the query will be performed and used in line 20, 23 and 26 to perform some queries. But if you look carefully you can see in line 31 we create another object from the query builder and assigned in db1 variable. Then we performed a Get query in line 37, this time we did not say the table name but it will perform the query on the users table because we set the table name before on the same object. No matter how many times you asked to create a DB object you will get the same object with the previous connection.

Well, where we used the Builder design pattern? If you look closely you can see all the three concrete implementations used builder design pattern to create complex SQL queries. If we add another method called Limit` we can implement limit definition for different dialects and if the client invokes the Limit method then it will add limit functionality.

Though we did not make a working query builder we simulate an idea to create them, basically we focused on how can we use the factory pattern, singleton pattern. If you need the full source code you’ll find it here.

Note: I’ll try to update all of my articles in this series. To get update follow me on twitter or medium. One more thing, if you find any mistake or misleading in these articles please knock me or write a comment. Thank you

If you like my writing please follow me Saddam H.

Software Engineer, Pathao Inc | Open Source Enthusiast | Love to write elegant code | Gopher by passion | https://thedevsaddam.github.io