Building RESTful APIs with Golang and Gorilla Mux

Michelle Sauder
Four Nine Digital
Published in
7 min readMar 20, 2024

At Four Nine Digital, we thrive on staying at the forefront of technology trends and fostering a culture of experimentation. In preparing for an upcoming project, I was tasked with exploring Golang, a language gaining prominence for its high performance and simplicity. In the dynamic world of API development, crafting efficient and scalable APIs isn’t just a skill; it’s a game-changer. Golang, with its performance, and Gorilla Mux, a robust HTTP router, are our tools of choice. Today, I’ll share my firsthand experiences in setting up my first Golang API. I was assigned to develop a Giphy generator application. Although this blog post won’t delve into the application itself, it will focus on the fundamental steps I took to initiate the API building process.

The Golang Advantage

Golang, also known as Go, has gained popularity for its clean syntax, concurrency support, and impressive execution speed. Developed by Google, Go is designed to be simple and productive, making it an excellent choice for building backend services, especially when performance is a priority. Its static typing and compiled nature ensure both safety and efficiency, while its concurrent programming features enable developers to create highly responsive applications.

Introducing Gorilla Mux

At the heart of our API-building adventure is Gorilla Mux, a powerful HTTP router and dispatcher for Go. Gorilla Mux provides a flexible and expressive way to handle HTTP requests, making it a popular choice for developers aiming to build RESTful APIs. Its rich set of features includes route matching, middleware support, and the ability to create clean and modular code.

What to Expect in This Walkthrough

Diagram showing how a client interacts with a Go application using Gorilla Mux for routing and HTTP request/response handling, crucial for building RESTful APIs.

This walkthrough will help you set up your initial application, serving as a starting point for your first real project. We’ll explore the fundamentals of building RESTful APIs, covering key aspects such as routing, handling HTTP requests and responses.

1. Prerequisites: Go, an IDE such as VSCode, VSCode Go extension.

2. Project Setup:

a. Create a file named main.go inside a new project directory.

//terminal

mkdir go-app
cd go-app
touch main.go

code . (opens project in VSCode - https://code.visualstudio.com/docs/setup/mac)

b. Next, execute go mod init my-app to start a fresh module in the present directory, generating a go.mod file for defining paths and managing dependencies.

//terminal

go mod init my-app

c. In your main.go file, designate it as the main file by specifying package main. Create a main function with func main() {} to declare the starting point of execution, and organize all your logic within this function.

//main.go

package main

func main() {}
Screenshot demonstrating the creation of the main.go file within a newly created project directory.

3. Install dependencies

//terminal

go get -u github.com/gorilla/mux

go get -u github.com/gorilla/handlers
Screenshot of a go.mod file, defining the Go project's module name and dependencies for versioning and management.

4. Create three folders inside of your server folder: router, model, api.

//terminal

mkdir api && mkdir router && mkdir models
Terminal screenshot demonstrating the creation of directories named ‘api’, ‘router’, and ‘models’ using the command ‘mkdir’.

5. Create a Simple Router:

a. Inside the router folder, create a file named router.go and define the package as package router.

//terminal

cd router
touch router.go

b. Import two external packages:

  • my-app/api: The “my-app/api” package in Go houses API functionalities, including HTTP request handling.
  • github.com/gorilla/mux: Gorilla Mux simplifies the creation of dynamic URL routers for Go web applications, enabling you to define URL patterns and link them to specific handlers or controller functions.
//router.go

package router

import (
"my-app/api"

"github.com/gorilla/mux"
)

c. Then, define a function named NewRouter inside of router.go that creates and configures an instance of the Gorilla Mux HTTP router:

Router Initialization:

  • r := mux.NewRouter() creates a new instance of the Gorilla Mux router and assigns it to the variable r.

Route Configuration:

  • r.HandleFunc(“/words/{search}”, ) configures a route on the router. The route is “/word/{search}”, where {search} is a placeholder for a dynamic value. The route is associated with the api.GetWord function handling API requests.
  • .Methods(“GET”) restricts the route to respond only to HTTP GET requests.
  • The configured router (r)is returned by the function.
//router.go

...

func NewRouter() *mux.Router {
r := mux.NewRouter()
r.HandleFunc("/word/{search}", api.GetWord).Methods("GET")
return r
}

6. In your api folder create a file called api.go and paste the following code with the appropriate import paths:

//terminal

cd ..
cd api
touch api.go

a. The GetWord function serves as an HTTP handler.

Parameters:

  • w http.ResponseWriter: Represents the HTTP response writer. This parameter allows the handler to construct an HTTP response to send back to the client.
  • r *http.Request: Represents the HTTP request received from the client. It contains information about the request, such as the HTTP method, headers, and any data sent by the client.

Extracting variables from HTTP request:

  • vars := mux.Vars(r): This line uses the mux package’s Vars function to extract the variables (parameters) from the given HTTP request r. The mux package is commonly used for routing in Go web applications
  • searchTerm, ok := vars[“search”]: This line attempts to retrieve the value associated with the key “search” from the map vars. The value is assigned to the variable searchTerm, and the boolean variable ok is set to true if the key is present, and false otherwise.

Creating and Sending JSON Responses:

  • responseData := ResponseData{SearchTerm: searchTerm}: Creates a JSON object named responseData using the ResponseData struct which will be created in the types.go file.
  • w.Header().Set(“Content-Type”, “application/json”): Sets the Content-Type header to indicate that the response is in JSON format.
  • json.NewEncoder(w).Encode(responseData): Serializes responseData to JSON and sends it as the HTTP response.

Error Handling:

  • if !ok {: Checks if the boolean variable ok is false, indicating that the search term is missing.
  • (if err := json.NewEncoder(w).Encode(responseData); err != nil {): Encodes responseData to JSON and checks for errors during the encoding process.
//api.go

package api

import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"

"my-app/models"
)

// GetWord handles HTTP requests for fetching data.
func GetWord(w http.ResponseWriter, r *http.Request) {
// Extract the search term from the request parameters.
vars := mux.Vars(r)
searchTerm, ok := vars["search"]
if !ok {
http.Error(w, "Missing search term in the request", http.StatusBadRequest)
return
}

// Create a JSON object (ResponseData) with the search term.
responseData := models.ResponseData{
SearchTerm: searchTerm,
}

// Set the Content-Type header to indicate that the response is in JSON format.
w.Header().Set("Content-Type", "application/json")

// Serialize the responseData to JSON and send it as the HTTP response.
if err := json.NewEncoder(w).Encode(responseData); err != nil {
// If there is an error during JSON encoding, respond with an Internal Server Error (500) and the error message.
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}

b. Inside of your model folder create a file called types.go and paste the following code:

//terminal

cd ..
cd models
touch types.go
  • The following Go struct, commonly used in applications, shapes data for JSON responses. The json tags guide encoding, specifying field representation in the JSON format.
//types.go

package models

// ResponseData represents the structure of the JSON response.
type ResponseData struct {
SearchTerm string `json:"searchTerm"`
}

7. Inside of your main.go file, tie everything together by adding the following code, which will:

  • Create a new router using router.NewRouter()
  • Enable CORS for the router with default options
  • Handle all requests with the created router
  • Start an HTTP server on port 8080 using http.ListenAndServe
  • Log an error message and exits if there’s an issue starting the server
//main.go

package main

import (
"fmt"
"log"
"net/http"

"github.com/gorilla/handlers"
"my-app/router"
)

func main() {
r := router.NewRouter()

// Enable CORS with default options
cors := handlers.CORS()(r)

// Start the HTTP server on port 8080
http.Handle("/", r)
fmt.Printf("starting server at port 8080")
log.Fatal(http.ListenAndServe(":8080", cors))
}

8. Finally, use a tool like Postman to run and test your HTTP request endpoint.

a. Run your backend with the following command from the root of your project:

//terminal

cd ..
go run main.go

Note: A warning sign may appear; simply press “Allow.”

Screenshot displaying a system warning asking whether to allow the ‘main’ application to accept network connections.

b. In Postman, create a GET request with the specified search term to receive the expected JSON response.

http://localhost:8080/word/trending
Postman screenshot: Creating a GET request with the specified search term and receiving the expected JSON response.

Building RESTful APIs with Golang and Gorilla Mux enables the creation of high-performance, scalable, and maintainable web applications. I trust this blog post has provided valuable insights, serving as a starting point for your Golang journey. Thanks for reading!

Four Nine is a full-service Digital Agency located in Vancouver, BC. Learn more about us by visiting our website or contact us at info@fournine.digital.

--

--

Michelle Sauder
Four Nine Digital

At Four Nine Digital, I craft web apps with meaningful solutions for diverse clients. With 2+ years experience, I deploy various languages & tech.