Sign in
Log inSign up

Go with ORM — Into the G(orm)hole

Uzair Ali's photo
Uzair Ali
·Dec 13, 2021·

5 min read

Into the Gormhole

Go with ORM — Into the G(orm)hole

Hey There!

This article is for developers looking for quick Go-ORM setup. We will be creating a Go backend with GORM, connecting it to Postgres DB and implement CRUD operations.

For a simple setup, without the ORM, you can read my article here

Go: What?

An ORM (Object Relational Mapping) is a programming technique for converting incompatible data types. Imagine two people speaking different languages trying to talk to each other, either they employ a translator or learn a common language for conversing. This is how the ORM basically works, converts the tables into Objects that can be used in the code, with all the advantages of object oriented programming.

Go: Why?

An ORM helps you to avoid repeated queries to database (DRY!). Since it maps your tables to an Object, you can use the table, like you would use an object. You can search inside the object, you can add values to your object, delete the object. All the fun you have with Object oriented programming, is now available to you with the database tables! This leads to a cleaner code. Also we won’t have to deal much with raw queries.

The one downside is that you have learn how to use the ORM library which you are implementing. Thankfully the Internet is full of tutorials like this one to help you on your journey.

ORM

Go: How?

We begin our journey into the G(orm)hole by structuring our code as follows

Folder structure

We create our module by running the command

$ go mod init <your-module-name>

Then we install the necessary packages

$ go get github.com/gorilla/mux
$ go get github.com/jinzhu/gorm

A go.mod and a go.sum file will be generated. These contain the module manifest and package checksum respectively. Now we start the actual coding.

The Post

We first define how the Post is stored and displayed to us. Enter the following code in the models/post.go file.

https://medium.com/media/e8d99550f738d20753860e9ebed5c186/href

  • The gorm.Model tells the compiler that the struct has to be mapped to a Table in the database.
  • The gorm:”type:varchar(255);” json:”title” makes the compiler understand that in the database, the GORM has to save it as varchar, but when displaying to the user it has to show json.
  • We add two functions to help us in creating a post or retrieving array of posts

Data used in different ways

The Database Connection

We need to connect to the database. GORM allows us to connect to the database with different dialects. Here we will be using the postgres dialect, as we are using Postgres DB in this tutorial. You can change it to other dialects if you are using other databases like MySQL, Sqlite3 etc.

Enter the following code in the file utility/database.go

https://medium.com/media/59d8065536aa2ac9de47f0f25ce4cfcb/href

Now our connection file is ready we will test it out. We just need to create a main file to call it.

The Main File

In the root folder of our application we create a main.go file. Add the following code.

https://medium.com/media/d1f129e2b4510d3aa5a11c9c3e7942c3/href

Run it using the command

$ go run main.go

It should output DB Connection established All is well! We are on the right track!

Now we will implement the code for CRUD operations

GET: ALL POSTS

We will create a route file which will tell what route the API has for which job.

Create a file routes/routes.go and add the following code

https://medium.com/media/20561d4c0c64e6197922fcf2ad0bf767/href

Now we create a service file, and add code to fetch all posts from the database.

Add the following code to the services/service.go file

https://medium.com/media/16f6dd1866b1832bb5840a1bc36fde4b/href

Notice the following components

  • func SetDB(db *gorm.DB) :- This creates a global connection of db available to the service. The AutoMigrate() function helps in creating tables in the database, if the tables didn’t exist. GORM does this for us, so that we don’t have to write the exhausting CREATE queries.
  • Response struct :- This is a response object created for the user to consume. We send this object when the status is 200 OK. This object will contain a data field to send the Post data and a message field to send message such as “SUCCESS” / “UPDATED” / “DELETED”

In the GetAllPosts function we create a response object, tell GORM to fetch all posts from the DB, check if any error occurred — if yes send the error with error status code; else add the posts fetched, to our response object, set message as SUCCESS and deliver it to the end user.

Now all we have to do, is integrate the files to main. The main file should have the following lines now.

https://medium.com/media/00de979719be2779f956aeb67cb80321/href

Run the application with $ go run main.go Hit the URL http://localhost:8000/posts It should give you an empty Response object with message SUCCESS.

Check the database, you will find a table named posts already created.

posts table
Believe in Magic yet?

We notice also that there are additional fields in the table than we bargained for. created_at, updated_at , deleted_at and id . What is happening?

GORM creates these fields automatically. id for indexing and primary key. _at fields for auditing. Isn’t that awesome?

Now we implement the rest of the operations.

GET: POST BY ID

Add the following function to services/service.go file

https://medium.com/media/43096f37e470e920c8fd919ebaa9def6/href

We have additional imports here strconv and github.com/gorilla/mux to parse the given path parameter or post id.

CREATE: POST

Add the following function to services/service.go file

https://medium.com/media/db97fe4a1f29c0a27eea73da2e6afac8/href

UPDATE: POST BY ID

Add the following function to services/service.go file

https://medium.com/media/1f4e1dff63f836201910eb6db4356649/href

Felt Cute! Might DELETE later

Add the following function to services/service.go file

https://medium.com/media/b9af5b49ca7b46fbe54a9a6fc87af538/href

GORM has a feature of Soft Delete. This means the record is not deleted from the database, but rather the deleted_at field is updated, and the record is not available for use. If you want the record again, you simply clear the deleted_at field of the record in the database.

If you need to erase the record completely from the database ( a hard DELETE) change the line

err := dbconn.Delete(&post, params["id"]).Error

to

err := dbconn.Unscoped().Delete(&post, params["id"]).Error

The Unscoped() makes hard delete of the record.

We have the operations implemented, all we have left to do, is make the routes available. Modify the routes/routes.go file as follows:

https://medium.com/media/3ef352a550c6fe6e18ad85a664c96d03/href

Now we are ready! Test the API in Postman

Storing some important conversation

We created a Go-Backend with ORM to connect to database and not a single raw query in sight! Ah! The feeling of pure bliss!

The entire code can be found here

There are more APIs and operations available in GORM. Check out the documentation here

Until we meet again! Be Safe! Code Safe! Bye!!