Build a RESTful API with GO and PostgreSQL.
By: Walugembe Peter
Tags: Postgresql, API, Rest Api, Gorm, Go

Why Go?

Go is an open-source programming language that makes it easy to build simple, reliable, and efficient software.

What we are going to build.

A venue manager API. This API will allow users to Create, Retrieve, Edit and Delete venues.

Prerequisites.

To follow along you will need to have these installed.

Go version 1.13, It is the version used to build this API.

PostgreSQL installed.

An IDE of choice, some of the recommended IDEs are listed here.

An API Request builder. e.g Postman.

I am assuming readers, have a basic understanding of Go.

API Specifications.

Endpoints we will have at the end of this article.

Register a user after a valid POST request at /register .

. Login user after a valid POST request at /login .

. Create a venue after a valid POST request at /api/venues .

. Get venues after a valid GET request at /api/venues .

. Edit a venue after a valid PUT request at /api/venues/id .

. Delete a venue after a valid DELETE request at /api/venues/id .

. Get a venue after a valid GET request at /api/venues/id .

Getting Dependencies.

These are the package dependencies we will need.

badoux/checkmail — for validating user emails.

dgrijalva/jwt-go — to sign and verify jwt tokens.

gorilla/mux — it is a router and dispatcher, for matching URLs to their handlers.

jinzhu/gorm — its an ORM(Object Relational Mapper) will enable us interact with the database.

joho/godotenv — to load .env file, which holds our secrets. e.g database passwords.

file, which holds our secrets. e.g database passwords. crypto — to hash and verify user passwords.

To install these dependencies, open the terminal and type

go get github.com/{package-name} e.g.

go get github.com/badoux/checkmail .

For crypto installation, type

go get golang.org/x/crypto .

Getting started.

Create a PostgreSQL database to store data.

Create .env file in the ivents folder which is the project folder. This the database credentials and secrets such as the SECRET for signing jwt tokens.

SECRET=anything-secret-and-should-be-hard-to-guess

DB_HOST=127.0.0.1

DB_USER=username

DB_PASSWORD=user-password

DB_NAME=database-name

DB_PORT=5432

In the ivents folder, create the api folder and in it create the models folder.

In the models folder, create a user.go file, in which the user structure is defined and database operations helper functions.

The project structure should appear as below.

ievents (project folder)

|--api

|--models

|-- user.go

|-- .env

Below is the user.go file.

models/user.go

This file contains the User struct which represents a user account, functions for cleaning and validating user input data. There are helper functions for querying, saving, updating and deleting users.

Struct tags below are used on the models.

gorm tag adds specifications on how the user table is be created i.e field types and sizes.

json tag is used by encoding/json package for encoding and decoding JSON data.

More information about struct tags can be found here.

This gorm.Model automatically adds fields such as created_at , updated_at and deleted_at so we do not explicitly add those.

Create the base.go file in the controllers folder, create the controllers folder in the api folder. This defines the app structure with references to the router and database used by the application.

base.go

The Initialize method sets up a database connection and runs migrations after the connection from the API is made to the database. The migrations are only run in case of a new table or changes to the structure of an existing table.

The initializeRoutes method matches URLs to handlers and sets Middlewares which are used for setting the content-type to JSON and Verifying Authentication Tokens.

The Runserver method starts the server on port 5000 and logs failures for troubleshooting.

The go-linter will throw errors about UserSignUp and Login not being found, they will be added shortly, so no worries.

To format responses from the API, create a json.go file in the responses folder. The responses folder should be in the api folder.

responses/json.go

The JSON method formats responses into JSON adds status codes and data to return to the user all in the response.

The Error method formats errors to JSON along with the error message and status code.

Middlewares.

These will allow the interception of requests to perform certain actions. Create a middlewares.go file in the middlewares folder, which is also in the api folder.

These middlewares will set the content-type to application/json and also verify user authentication tokens.

middlewares.go

The SetContentTypeMiddleware sets the content-type to JSON a format the API will use.

The AuthJWTVerify verifies user authentication tokens which are acquired at login. After successful verification, the user's ID is added to the request context. This middleware will only allow authenticated users access to protected API routes such as Venue creation.

Access Tokens.

Create a file token.go in the utils folder. The utils should be in the ivents folder.

This encodes information about users in tokens, time token is issued, and its expiry time. The token is then signed off with the secret in the .env file. Below is the file.

utils/tokens.go

User Registration and Login.

Create a userController.go file in the controllers folder. The file adds functionality for creating new users and logging in users. Below is the file.

usercontroller.go

User input is read from the request, then decoded into the user struct. Any white spaces are stripped away from the input and then validated.

For User registration, a check to ensure no existing user with the same email is saved, and an error indicating user with that email is already registered, if the passes the user password is hashed.

The input is then saved to the database creating a new user. A response indicating success is returned or a detailed error message in case of a failure.

For user login, the password from user input is verified with the stored user password hash to check for a match, and an access token is generated. The token along with a success message is returned or error in case of a failed password match.

Create an application entry point.

Create a main.go file in the ivents folder. Here the app is initialized and environment variables loaded from the .env file.

main.go

Current App structure.

The project should be structured as below.

ivents

| -- api

| -- controllers

| -- base.go

| -- userControllers.go

| -- middlewares

| -- middlwares.go

| -- models

| -- user.go

| -- responses

| -- json.go

| -- utils

| -- token.go

| -- .env

| -- main.go

Run application.

To test the application. Open the terminal and type this command below to start the application go run main.go

Using Postman, an API request builder.

Test the create user functionality, as shown below by making a POST request to this URL http://localhost:5000/register and a body with the firstname , lastname , email and password . Content-type must be set to application/json .

create-user

Test the Login functionality too.

To add functionality for managing Venues. Create a venue.go file in the models folder. This file defines the venue structure and functions for database interactions.

venue.go

Create a venueControllers.go file under the controllers folder.

Here we get user input from the request in JSON format, then decode it into the venue struct, strip away any white space and validate it.

Check to ensure no other venue has a similar name before the data is saved or updated.

Check to ensure users can only update and delete their venue, using the venue userID.

The userIDs are obtained from r.Context().Value("userID") . The ID is added to the request context in the AuthJwtVerify middleware.

venueControllers.go

Update the base.go file in the controllers folder, to add the new routes for CRUD venues functionality.

These routes will only be accessed with an Authorization token, a sub router on which the AuthJwtVerify middleware is set, which will check requests to ensure they have a valid token is passed.

The venues model is added to the Initialize function for migration.

Below is the base.go file.

base.go

Start the server with go run main.go to test the new endpoints for creating, editing and deleting venues.

In the follow-up article, we will write tests for all the functionality.

This being a very long article, thanks for reading. CHEERS!!.

The code can be found here .

Like this article, please reach out on twitter @peterwade153. Email at peterwade153@gmail.com.

References. I used Kulshekhar Kabra’s article as a reference. It can be found here.