Building a REST API with Go and Gorilla Mux

 


Go (or Golang) is a popular language for building web applications due to its simplicity, performance, and built-in support for concurrency. One of the most common tasks in web development is creating a REST API to serve data to clients. In this guide, we’ll explain how to build a REST API in Go using the Gorilla Mux router.

Gorilla Mux is a powerful HTTP request router and URL matcher for building Go web servers. It provides features like URL variables, middleware support, and routing based on HTTP methods (GET, POST, PUT, DELETE).

Let’s dive into the process of building a REST API with Go and Gorilla Mux step by step.


Table of Contents

  1. What is REST API?
  2. Installing Gorilla Mux
  3. Setting Up the Go Project
  4. Creating a Basic REST API
    • Defining Models
    • Defining Routes
  5. Handling HTTP Methods
    • GET, POST, PUT, DELETE
  6. Middleware
  7. JSON Handling in Go
  8. Error Handling
  9. Testing the API
  10. Running the Application

1. What is REST API?

A REST API (Representational State Transfer) is a set of web services that allow client applications to interact with a backend server via HTTP requests. It uses standard HTTP methods like GET, POST, PUT, and DELETE to perform operations on resources.

In REST APIs:

  • Resources (like users, products, etc.) are identified by URLs.
  • HTTP methods determine the type of operation performed on a resource:
    • GET: Retrieve data
    • POST: Create new data
    • PUT: Update existing data
    • DELETE: Delete data

For example, a simple URL to retrieve a list of users could be:


GET /api/users

To create a new user:


POST /api/users

2. Installing Gorilla Mux

To get started with Gorilla Mux in Go, you first need to install it. Gorilla Mux is available as a Go module, and you can install it using go get.

Run the following command to install Gorilla Mux:


go get -u github.com/gorilla/mux

Once Gorilla Mux is installed, you can start using it to handle HTTP routing in your application.


3. Setting Up the Go Project

Let’s start by creating a basic structure for the project. For this example, let’s assume we’re building an API to manage books in a library system.

  1. Create a new directory for your project:

mkdir go-book-api cd go-book-api
  1. Initialize the Go module:

go mod init go-book-api
  1. Create a new file called main.go where the main application will reside.

4. Creating a Basic REST API

Let’s define the basic structures needed for a book management API. We will define:

  • Book Model: A simple struct to represent the book.
  • Handlers: Functions that handle requests for various HTTP methods.
  • Router: Using Gorilla Mux to map URLs to handlers.

4.1 Defining the Book Model

In main.go, let’s define the Book struct, which will represent a book in our library.


package main import ( "encoding/json" "fmt" "log" "net/http" "github.com/gorilla/mux" ) // Book struct to hold book data type Book struct { ID string `json:"id"` Title string `json:"title"` Author string `json:"author"` Price float64 `json:"price"` }

In this code:

  • ID: A unique identifier for the book.
  • Title: The title of the book.
  • Author: The author of the book.
  • Price: The price of the book.

4.2 Defining Routes and Handlers

Now, let’s define the routes that will handle the GET, POST, PUT, and DELETE operations for books. We’ll create functions for each HTTP method to handle the request.


// Global slice to store books var books []Book // GetBooks handler to return all books func GetBooks(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(books) } // CreateBook handler to add a new book func CreateBook(w http.ResponseWriter, r *http.Request) { var book Book _ = json.NewDecoder(r.Body).Decode(&book) books = append(books, book) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(book) } // GetBookByID handler to get a book by ID func GetBookByID(w http.ResponseWriter, r *http.Request) { id := mux.Vars(r)["id"] for _, book := range books { if book.ID == id { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(book) return } } http.Error(w, "Book not found", http.StatusNotFound) } // UpdateBook handler to update an existing book func UpdateBook(w http.ResponseWriter, r *http.Request) { id := mux.Vars(r)["id"] var updatedBook Book _ = json.NewDecoder(r.Body).Decode(&updatedBook) for i, book := range books { if book.ID == id { books[i] = updatedBook w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(updatedBook) return } } http.Error(w, "Book not found", http.StatusNotFound) } // DeleteBook handler to delete a book by ID func DeleteBook(w http.ResponseWriter, r *http.Request) { id := mux.Vars(r)["id"] for i, book := range books { if book.ID == id { books = append(books[:i], books[i+1:]...) w.WriteHeader(http.StatusNoContent) return } } http.Error(w, "Book not found", http.StatusNotFound) }

Here’s a breakdown of what each handler does:

  • GetBooks: Returns a list of all books in JSON format.
  • CreateBook: Accepts a new book in the request body and adds it to the books list.
  • GetBookByID: Searches for a book by its ID and returns it in JSON format.
  • UpdateBook: Updates an existing book by ID with data from the request body.
  • DeleteBook: Deletes a book by ID.

4.3 Setting Up the Router

Now, we need to set up the Gorilla Mux router to map the HTTP requests to their respective handlers.


func main() { // Initialize some sample books books = append(books, Book{ID: "1", Title: "1984", Author: "George Orwell", Price: 9.99}) books = append(books, Book{ID: "2", Title: "To Kill a Mockingbird", Author: "Harper Lee", Price: 7.99}) // Create a new router router := mux.NewRouter() // Define routes router.HandleFunc("/api/books", GetBooks).Methods("GET") router.HandleFunc("/api/books", CreateBook).Methods("POST") router.HandleFunc("/api/books/{id}", GetBookByID).Methods("GET") router.HandleFunc("/api/books/{id}", UpdateBook).Methods("PUT") router.HandleFunc("/api/books/{id}", DeleteBook).Methods("DELETE") // Start the server log.Fatal(http.ListenAndServe(":8080", router)) }

In the main function:

  • We initialize a few sample books in the books slice.
  • We set up a new router using Gorilla Mux with mux.NewRouter().
  • We define the routes and associate them with the corresponding handler functions.
  • Finally, we start the HTTP server on port 8080 using http.ListenAndServe.

5. Handling HTTP Methods

We’ve already discussed how to handle different HTTP methods for our API:

  • GET: Retrieve data (either all resources or a specific resource by ID).
  • POST: Create a new resource (a new book).
  • PUT: Update an existing resource (update a book).
  • DELETE: Delete an existing resource (delete a book by ID).

These handlers are linked to specific routes, and Gorilla Mux takes care of routing the request to the correct handler based on the URL and HTTP method.


6. Middleware

Middleware in Go is a function that wraps HTTP requests and can perform additional tasks, such as logging, authentication, and error handling. You can apply middleware to individual routes or to all routes globally.

Here’s an example of a simple logging middleware:


func LoggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Printf("Request: %s %s\n", r.Method, r.URL) next.ServeHTTP(w, r) }) } func main() { // Initialize books and router as before // ... // Create a new router router := mux.NewRouter() // Apply middleware router.Use(LoggingMiddleware) // Define routes // ... }

In this example, the LoggingMiddleware prints out the HTTP method and URL of every incoming request.


7. JSON Handling in Go

One of the most common tasks when building a REST API is working with JSON data. Go’s encoding/json package makes it easy to encode and decode JSON.

In our handlers:

  • We use json.NewEncoder(w).Encode(data) to send a Go struct as JSON in the response.
  • We use json.NewDecoder(r.Body).Decode(&data) to read JSON from the request body and convert it into a Go struct.

8. Error Handling

Good error handling is crucial for a REST API. In the example above, we used http.Error to return error responses when a resource is not found.

You can also return specific status codes and error messages:


http.Error(w, "Book not found", http.StatusNotFound)

For more complex APIs, you can define custom error types and use middleware to handle errors globally.


9. Testing the API

You can test the API using tools like Postman, cURL, or any HTTP client to send requests to your API.

Example cURL Commands:

  • GET all books:


    curl http://localhost:8080/api/books
  • POST a new book:


    curl -X POST -H "Content-Type: application/json" -d '{"id":"3", "title":"Go Programming", "author":"John Doe", "price": 19.99}' http://localhost:8080/api/books
  • PUT update a book:


    curl -X PUT -H "Content-Type: application/json" -d '{"id":"1", "title":"1984", "author":"George Orwell", "price": 8.99}' http://localhost:8080/api/books/1
  • DELETE a book:


    curl -X DELETE http://localhost:8080/api/books/1

10. Running the Application

To run your Go API, use the following command in your terminal:


go run main.go

The server will start running on http://localhost:8080. You can then test your API using the methods mentioned above.


Conclusion

In this tutorial, we’ve built a simple REST API in Go using Gorilla Mux. We’ve covered:

  • How to define models for resources (like books).
  • How to create routes and map them to HTTP handlers.
  • How to handle HTTP methods (GET, POST, PUT, DELETE).
  • How to apply middleware for additional functionality (like logging).
  • How to work with JSON in Go.
  • How to handle errors and test the API.

This forms a solid foundation for building more advanced APIs with Go. You can extend this API by adding more features, such as user authentication, database integration, and complex business logic.

Post a Comment

Cookie Consent
Zupitek's serve cookies on this site to analyze traffic, remember your preferences, and optimize your experience.
Oops!
It seems there is something wrong with your internet connection. Please connect to the internet and start browsing again.
AdBlock Detected!
We have detected that you are using adblocking plugin in your browser.
The revenue we earn by the advertisements is used to manage this website, we request you to whitelist our website in your adblocking plugin.
Site is Blocked
Sorry! This site is not available in your country.