Very basic Gorilla Mux tutorial in Go
A simple tutorial on how to make a REST API with Gorilla mux package in Go in simple steps.

Search for a command to run...
A simple tutorial on how to make a REST API with Gorilla mux package in Go in simple steps.

No comments yet. Be the first to comment.
Introduction This article is about how I upgraded my previous cron scheduler service that I built in Go for scaling it to around 1 million daily scheduled jobs. This lays out the overall system design, approach and considerations I took in building t...

Introduction This project is about a cron scheduler service which schedules cron jobs that are created using a dashboard interface. It publishes the jobs to the consumer service through RabbitMQ job queue, where it acknowledges successful job executi...

A simple guide about optimal project structure for backend projects in golang

Introduction Golang has made it very simple to apply concurrency in our programs and worker pool is one of the amazing concurrency pattern that we can simply create with go. Definition The technical definition is: (Yes, I copied this from internet 🙂...

Hello DEV fam, today I will be showing you how to create a basic REST API in Go language using Gorilla mux package with very simple steps, so even if your are very new to this amazing language you can follow this tutorial without any hesitation and problems. So now let's get right into it!
We will be creating a very very basic REST Api on our localhost to serve various GET POST PUT DELETE requests.
As this is going to be a beginner's tutorial to Gorilla Mux package, so we will not be looking into any of the database queries. We are going to use a sample data collection to assume it as a data coming from some database.
So without any delays let's get started.
But wait wait wait... You may ask what should I know in advance to follow this tutorial?
Hmm... Nothing fancy, just basics of Go language and that's it!
Else I will be explaining you about using & designing basic Crud REST API.
We are going to create a simple application where,
Getting list of users in response to valid GET request at /users
Getting an user in response to valid GET request at /user/{id}
Creating an user in response to valid POST request at /user
Updating an user in response to valid PUT request at /user/{id}
Deleting an user in response to valid DELETE request at /user/{id}
Initialize your project folder by creating a folder where we will be writing our code.
So begin with following commands in your terminal.
First to create the folder and another to move into that folder
mkdir go-mux-tut
cd go-mux-tut
Now initialize the GO modules using a github repo follow up address
go mod init github.com/user_name/repo_name
Now, it's time to fetch the required Gorilla Mux module into our project using following commandmux package - The Gorilla Mux router (also known as "HTTP request multiplexer")
go get -u github.com/gorilla/mux
create main.go app.go model.go controller.go in the project folder
So our project structure now looks something like this:
-app.go
-controller.go
-model.go
-main.go
-go.mod
-go.sum
Now the basic setup of project is completed, let's get started with coding!
First starting with app.go file, create a new router variable Router using mux.NewRouter() from the mux package, for this import "github.com/gorilla/mux"
var Router = mux.NewRouter()
Now let's create a function HandleRoutes() to handle different routes serving on this Router
func HandleRoutes() {
Router.HandleFunc("/users", GetAllUsers).Methods("GET")
Router.HandleFunc("/user/{id}", GetUser).Methods("GET")
Router.HandleFunc("/user", CreateUser).Methods("POST")
Router.HandleFunc("/user/{id}", UpdateUser).Methods("PUT")
Router.HandleFunc("/user/{id}", DeleteUser).Methods("DELETE")
}
Here using Router from the mux package, we create different routes using HandleFunc() function which takes string path and a function of http.ResponseWriter, *http.Response called controllers
We defined:
GetAllUsers controller, with method GET to get all the users GET to get user with specified id POST to create a new user. In this we will be passing new user's data in request bodyPUT to update an existing user and we will be passing the updated data in request bodyDELETE to delete an user app.go file looks like thispackage main
import (
"github.com/gorilla/mux"
)
var Router = mux.NewRouter()
func HandleRoutes() {
Router.HandleFunc("/users", GetAllUsers).Methods("GET")
Router.HandleFunc("/user/{id}", GetUser).Methods("GET")
Router.HandleFunc("/user", CreateUser).Methods("POST")
Router.HandleFunc("/user/{id}", UpdateUser).Methods("PUT")
Router.HandleFunc("/user/{id}", DeleteUser).Methods("DELETE")
}
To work with Request and serving Responses, we need to first have the data.
For this we will first create the User struct
type User struct {
ID int `json:"id"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
This User struct has an ID of type int with it's json name as id, FirstName of type string with it's json name as firstName, LastName of type string with it's json name as lastName
Now we will create a sample slice of users to work with
var UsersData = []User{
User{1, "Stephanie", "Turner"},
User{2, "Anna", "Edmunds"},
User{3, "Jan", "Vaughan"},
User{4, "Grace", "North"},
User{5, "Piers", "Morrison"},
}
model.go file looks like thispackage main
type User struct {
ID int `json:"id"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
var UsersData = []User{
User{1, "Stephanie", "Turner"},
User{2, "Anna", "Edmunds"},
User{3, "Jan", "Vaughan"},
User{4, "Grace", "North"},
User{5, "Piers", "Morrison"},
}
Now comes the important part, i.e creating the controllers which are the functions responsible for serving different paths of our simple API.
We're first required to import some packages, which are encoding/json, math/rand, net/http, strconv, github.com/gorilla/mux
Usage of each package will be explained further
import (
"encoding/json"
"math/rand"
"net/http"
"strconv"
"github.com/gorilla/mux"
)
GetAllUsers Function to return all usersfunc GetAllUsers(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(UsersData)
}
Let's understand each component of this function,
we have two parameters here, w http.ResponseWriter which has a Write method which accepts a byte slice and writes the data to the connection as part of an HTTP response and r *http.Request which deals with the request stuff.
We then define the type of Data we are sending using the Content-Type parameter in response's header and setting it as application/json to send json type data
Then finally we send the response by encoding the data to json format
GetUser Function to send an user with specific idfunc GetUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
vars := mux.Vars(r)
paramId, _ := strconv.Atoi(vars["id"])
for _, user := range UsersData {
if user.ID == paramId {
json.NewEncoder(w).Encode(user)
return
}
}
}
In this, we first get the map[string]string of parameters from the request r using mux.Vars(r)
As in our case, we need the id as int type, so we then get the id from vars map and then convert it to int type using strconv package.
Then we run a loop over our UsersData and find the user with this id, then return it in response.
CreateUser Function to create a new userfunc CreateUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Conent-Type", "application/json")
var user User
user.ID = rand.Intn(10000)
json.NewDecoder(r.Body).Decode(&user)
UsersData = append(UsersData, user)
msg := "User created successfully"
json.NewEncoder(w).Encode(ResponseMsg{msg, user})
}
In this, we first created a new user and assigned it with a random id within a range of 10000 using math/rand package.
Then we access the data we got in request body and decode it from json format to our User struct type and store it in user variable. Then finally we store this received user into our UsersData slice.
To send a response also with message, we have created another struct called ResponseMsg , which has a message and user data to send
type ResponseMsg struct {
Msg string `json:"message"`
User User `json:"user"`
}
Then we send this response with a message of "User created successfully" and created user's data
DeleteUser Functionfunc DeleteUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Conent-Type", "application/json")
vars := mux.Vars(r)
paramId, _ := strconv.Atoi(vars["id"])
for index, user := range UsersData {
if user.ID == paramId {
UsersData = append(UsersData[:index], UsersData[index+1:]...)
}
}
msg := "User deleted successfully"
json.NewEncoder(w).Encode(msg)
}
In this we have mentioned the header's Content-Type and got the id from requested path as we did earlier.
Then we ran a loop over the User's data to find the required user by comparing user's id with passed id.
When we get the required user, now we need to remove i.e delete this user from our UsersData slice.
To do so, we apply slicing using append() function by first cutting the original slice from 0th index upto that user's index , and then combining it with rest of the slice from user's index+1th position until last position.
Then finally we send a response with a message of "User deleted successfully"
UpdateUser Function, to update an userfunc UpdateUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Conent-Type", "application/json")
vars := mux.Vars(r)
paramId, _ := strconv.Atoi(vars["id"])
for index, user := range UsersData {
if user.ID == paramId {
UsersData = append(UsersData[:index], UsersData[index+1:]...)
}
}
var user User
user.ID = paramId
json.NewDecoder(r.Body).Decode(&user)
UsersData = append(UsersData, user)
msg := "User updated successfully"
json.NewEncoder(w).Encode(ResponseMsg{msg, user})
}
This has a little complex logic... No worries, let's understand it line by line.
So first we defined the header and got the id from request path as we have done earlier.
After that we ran a loop over the UsersData to find the user with that id, and here we first delete this user using above DeleteUser's logic.
Now the old id's user is deleted, we then create a new user with that same id and then add it to the UsersData slice.
In this manner, we have successfully updated the user.
We then send a response with a message saying "User updated successfully" along with the updated user's data.
controller.go file look like thispackage main
import (
"encoding/json"
"math/rand"
"net/http"
"strconv"
"github.com/gorilla/mux"
)
func GetAllUsers(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(UsersData)
}
func GetUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
vars := mux.Vars(r)
paramId, _ := strconv.Atoi(vars["id"])
for _, user := range UsersData {
if user.ID == paramId {
json.NewEncoder(w).Encode(user)
return
}
}
}
type ResponseMsg struct {
Msg string `json:"message"`
User User `json:"user"`
}
func CreateUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Conent-Type", "application/json")
var user User
user.ID = rand.Intn(10000)
json.NewDecoder(r.Body).Decode(&user)
UsersData = append(UsersData, user)
msg := "User created successfully"
json.NewEncoder(w).Encode(ResponseMsg{msg, user})
}
func UpdateUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Conent-Type", "application/json")
vars := mux.Vars(r)
paramId, _ := strconv.Atoi(vars["id"])
for index, user := range UsersData {
if user.ID == paramId {
UsersData = append(UsersData[:index], UsersData[index+1:]...)
}
}
var user User
user.ID = paramId
json.NewDecoder(r.Body).Decode(&user)
UsersData = append(UsersData, user)
msg := "User updated successfully"
json.NewEncoder(w).Encode(ResponseMsg{msg, user})
}
func DeleteUser(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Conent-Type", "application/json")
vars := mux.Vars(r)
paramId, _ := strconv.Atoi(vars["id"])
for index, user := range UsersData {
if user.ID == paramId {
UsersData = append(UsersData[:index], UsersData[index+1:]...)
}
}
msg := "User deleted successfully"
json.NewEncoder(w).Encode(msg)
}
Now we have only created different components of our API, now it's time to connect all the components in main.go file
Now we need to get the Router from app.go file and call HandleRoutes() function.
So first let's import the required packages which are fmt, log, net/http
import (
"fmt"
"log"
"net/http"
)
To start the server, we need to call the ListenAndServe function from net/http package by passing the port address i.e 8000 in our case and the router which we have created in app.go file
fmt.Println("Server started on port:8000")
log.Fatal(http.ListenAndServe(":8000", r))
main.go file looks like thispackage main
import (
"fmt"
"log"
"net/http"
)
func main() {
r := Router
HandleRoutes()
fmt.Println("Server started on port:8000")
log.Fatal(http.ListenAndServe(":8000", r))
}
Finally here we are, done with creating the very basic API using Gorilla Mux in Go.
Now it's time to check our API using POSTMAN.
To test our api we need to run our main.go file, so enter following command in terminal while being in the project folder
go run .
You will get output something like this
Server started on port:8000
Now your api server has been started on localhost at port 8000 and this can be accessed at "http://localhost:8000"
"localhost:8000/users" and keeping the methods as GET
"localhost:8000/user/3" to get the user with id 3. You can user another id in place of 3.
"localhost:8000/user", then open Header tab and set Content-Type to application/json
Then create the request body from Body tab

Now set the method type to POST and hit Send,
Then we get a response somthing like this:

And when you will again run get all user request, you can see the changes
"localhost:8000/user/1" and mention the Header as done above.
Now set the method as PUT and hit Send
So the response will look like:

"localhost:8000/user/1" by keeping the method as DELETE
You will get following response:
Gorilla mux is an amazing package to work with and build APIs easily and efficiently. This was a simple example using a sample slice data. But we can use different databases like Relational SQL databases like MySQL, PostgreSQL, etc or NoSQLs like MongoDB, Redis,etc or Cloud databases like dynamoDB, etc.
Relax, no need to worry after listening all these advance techs. I will be making detailed tutorials on each just like this so stay tuned and Subscribe to our newsletter and never miss any upcoming articles and Follow me for more.
Here is the link for the Github repository of this project:
%[https://github.com/Aniketyadav44/go-mux-tut]
LinkedIn Github Website Twitter Instagram