Skip to main content

Command Palette

Search for a command to run...

Building a Simple REST API in Go

Updated
5 min read
Building a Simple REST API in Go
J

"Hello! I'm a passionate Software Engineer dedicated to the ever-evolving world of technology. With a deep love for coding and a commitment to continuous learning, I've found my true calling in the realm of software development. Each day is a new adventure as I explore the latest trends, techniques, and technologies in the tech industry.

My blog, 'Pondering Programmer', is a reflection of my journey: a mix of insights, discoveries, and practical tips from the front lines of coding. Whether you're a fellow tech enthusiast, a budding developer, or just curious about the digital world, join me as I unravel the mysteries of code and share my daily learnings in this fascinating and dynamic field.

Let's embark on this tech adventure together, learning, growing, and coding our way to new possibilities!"

If you're new to Go (often referred to as Golang) and want to learn how to build a RESTful API, you're in the right place! This guide will walk you through the process step-by-step, providing code examples to help you understand how everything fits together.

What is a REST API?

A REST (Representational State Transfer) API is a way for applications to communicate over HTTP using standard methods like GET, POST, PUT, and DELETE. RESTful APIs are stateless and can be used across various platforms and languages, making them a popular choice for web services.

Why Use Go for REST APIs?

Go is a statically typed, compiled language known for its simplicity and performance. It's excellent for building web services due to its efficient concurrency model and robust standard library, which includes powerful packages for handling HTTP requests.

Prerequisites

Before we begin, make sure you have:

  • Go installed on your system. You can download it from the official website.simp

  • A basic understanding of Go syntax and programming concepts.

  • A code editor or IDE you're comfortable with (e.g., VSCode, GoLand).

Setting Up Your Go Project

First, create a new directory for your project and navigate into it:

mkdir simple-rest-api
cd simple-rest-api

Initialize a new Go module:

go mod init github.com/yourusername/simple-rest-api

Replace github.com/yourusername/simple-rest-api with your module path.

Building the REST API

We'll build a simple API to manage a list of books. The API will support the following operations:

  • Get a list of all books (GET)

  • Get a single book by ID (GET)

  • Add a new book (POST)

  • Update an existing book (PUT)

  • Delete a book (DELETE)

Creating a Simple Server

Let's start by creating a basic HTTP server.

Create a file named main.go and add the following code:

package main

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

func main() {
    http.HandleFunc("/", homePage)
    fmt.Println("Server starting on port 8080...")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func homePage(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Welcome to the Simple REST API in Go!")
}

Run the server:

go run main.go

Visit http://localhost:8080 in your browser, and you should see "Welcome to the Simple REST API in Go!"

Defining a Data Model

Let's define a Book struct to represent our data model.

Add the following code to main.go:

type Book struct {
    ID     string `json:"id"`
    Title  string `json:"title"`
    Author string `json:"author"`
}

var books []Book

Initialize some sample data:

func init() {
    books = []Book{
        {ID: "1", Title: "1984", Author: "George Orwell"},
        {ID: "2", Title: "To Kill a Mockingbird", Author: "Harper Lee"},
        {ID: "3", Title: "The Great Gatsby", Author: "F. Scott Fitzgerald"},
    }
}

Implementing API Endpoints

Get All Books

Add the following handler function:

func getBooks(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(books)
}

Don't forget to import the encoding/json package at the top:

import (
    "encoding/json"
    // other imports
)

Update the main function to handle this route:

func main() {
    http.HandleFunc("/", homePage)
    http.HandleFunc("/books", getBooks)
    // rest of the code
}

Now, when you navigate to http://localhost:8080/books, you should see the list of books in JSON format.

Get a Single Book

Add the handler function:

func getBook(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    id := r.URL.Query().Get("id")
    for _, book := range books {
        if book.ID == id {
            json.NewEncoder(w).Encode(book)
            return
        }
    }
    http.Error(w, "Book not found", http.StatusNotFound)
}

Update main to handle this route:

func main() {
    http.HandleFunc("/", homePage)
    http.HandleFunc("/books", getBooks)
    http.HandleFunc("/book", getBook)
    // rest of the code
}

Now you can get a single book by ID: http://localhost:8080/book?id=1

Add a New Book

Add the handler function:

func createBook(w http.ResponseWriter, r *http.Request) {
    if r.Method != "POST" {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    w.Header().Set("Content-Type", "application/json")
    var newBook Book
    err := json.NewDecoder(r.Body).Decode(&newBook)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    books = append(books, newBook)
    json.NewEncoder(w).Encode(newBook)
}

Update main:

func main() {
    http.HandleFunc("/", homePage)
    http.HandleFunc("/books", getBooks)
    http.HandleFunc("/book", getBook)
    http.HandleFunc("/book/create", createBook)
    // rest of the code
}

Now you can add a new book by sending a POST request to http://localhost:8080/book/create with a JSON body.

Update a Book

Add the handler function:

func updateBook(w http.ResponseWriter, r *http.Request) {
    if r.Method != "PUT" {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    w.Header().Set("Content-Type", "application/json")
    id := r.URL.Query().Get("id")
    var updatedBook Book
    err := json.NewDecoder(r.Body).Decode(&updatedBook)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    for i, book := range books {
        if book.ID == id {
            books[i] = updatedBook
            json.NewEncoder(w).Encode(updatedBook)
            return
        }
    }
    http.Error(w, "Book not found", http.StatusNotFound)
}

Update main:

func main() {
    http.HandleFunc("/", homePage)
    http.HandleFunc("/books", getBooks)
    http.HandleFunc("/book", getBook)
    http.HandleFunc("/book/create", createBook)
    http.HandleFunc("/book/update", updateBook)
    // rest of the code
}

You can update a book by sending a PUT request to http://localhost:8080/book/update?id=1.

Delete a Book

Add the handler function:

func deleteBook(w http.ResponseWriter, r *http.Request) {
    if r.Method != "DELETE" {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    w.Header().Set("Content-Type", "application/json")
    id := r.URL.Query().Get("id")
    for i, book := range books {
        if book.ID == id {
            books = append(books[:i], books[i+1:]...)
            fmt.Fprintf(w, "Book with ID %s deleted", id)
            return
        }
    }
    http.Error(w, "Book not found", http.StatusNotFound)
}

Update main:

func main() {
    http.HandleFunc("/", homePage)
    http.HandleFunc("/books", getBooks)
    http.HandleFunc("/book", getBook)
    http.HandleFunc("/book/create", createBook)
    http.HandleFunc("/book/update", updateBook)
    http.HandleFunc("/book/delete", deleteBook)
    // rest of the code
}

Now you can delete a book by sending a DELETE request to http://localhost:8080/book/delete?id=1.

Testing the API

You can test the API endpoints using a tool like Postman or curl.

Example with curl

  • Get all books

      curl http://localhost:8080/books
    
  • Get a single book

      curl http://localhost:8080/book?id=1
    
  • Create a new book

      curl -X POST -H "Content-Type: application/json" -d '{"id":"4","title":"Brave New World","author":"Aldous Huxley"}' http://localhost:8080/book/create
    
  • Update a book

      curl -X PUT -H "Content-Type: application/json" -d '{"id":"4","title":"Brave New World Revisited","author":"Aldous Huxley"}' http://localhost:8080/book/update?id=4
    
  • Delete a book

      curl -X DELETE http://localhost:8080/book/delete?id=4
    

Conclusion

Congratulations! You've built a simple REST API in Go. This basic API can be expanded and improved in many ways, such as adding a database, using a router package for cleaner route handling, and implementing proper error handling and logging.

Next Steps

  • Use a Router Package: Packages like gorilla/mux or chi can make route handling cleaner and more efficient.

  • Connect to a Database: Instead of using an in-memory slice, connect your API to a database like PostgreSQL or MongoDB.

  • Implement Middleware: Add middleware for logging, authentication, and request validation.


By understanding these basics, you're well on your way to building robust and efficient web services in Go. Happy coding!

K

The progression from a basic HTTP server to defining data models with structs and then implementing CRUD endpoints made the Go learning curve much more approachable. The curl examples at the end are particularly useful — being able to immediately test each endpoint removes the friction of needing a separate tool to verify your API works.

E

For many people and businesses, navigating the frequently dangerous landscape of financial loss can be an intimidating and overwhelming process. Nevertheless, the knowledgeable staff at Wizard Hilton Cyber Tech provides a ray of hope and direction with their indispensable range of services. Their offerings are based on a profound grasp of the far-reaching and terrible effects that financial setbacks, whether they be the result of cyberattacks, data breaches, or other unforeseen tragedies, can have. Their highly-trained analysts work tirelessly to assess the scope of the damage, identifying the root causes and developing tailored strategies to mitigate the fallout. From recovering lost or corrupted data to restoring compromised systems and securing networks, Wizard Hilton Cyber Tech employs the latest cutting-edge technologies and industry best practices to help clients regain their financial footing. But their support goes beyond the technical realm, as their compassionate case managers provide a empathetic ear and practical advice to navigate the emotional and logistical challenges that often accompany financial upheaval. With a steadfast commitment to client success, Wizard Hilton Cyber Tech is a trusted partner in weathering the storm of financial loss, offering the essential services and peace of mind needed to emerge stronger and more resilient than before. Call; Email : wizardhiltoncybertech ( @ ) gmail (. ) com
OR support ( @ ) wizardhiltoncybertech (.) com

WhatsApp number +13024457895