DEV Community

Cover image for Building Your First REST API with Go
Neel Patel
Neel Patel

Posted on • Updated on

Building Your First REST API with Go

Building Your First REST API with Go – Let’s Get Started!

So, you’ve heard the buzz about Go, right? It’s fast, it’s simple, and it’s basically the rockstar of backend development these days. If you’re new to Go or just looking to build something cool with it, you’ve come to the right place. This week, we’re going to take a dive into building your very own REST API with Go, so buckle up—it’s gonna be a fun ride!

Why Go?

Now, why exactly are so many devs swooning over Go? Well, imagine this: Google engineers, tired of waiting around for their programs to compile, decided to create something that wouldn't make them want to tear their hair out. Enter Go—a language that doesn’t just get the job done but does it fast and effortlessly.

Go is built for today’s hardware, taking full advantage of multi-core systems. Its secret weapon? Goroutines—these magical little concurrent workers that can handle tons of tasks simultaneously without breaking a sweat. Whether you’re building web apps, APIs, or microservices, Go keeps things running smoothly, like that well-oiled machine you always dream of.

And here’s the kicker: Go is stupidly easy to learn. Whether you’re switching over from Python, Java, or even something as “classic” as PHP, you’ll be up and coding in Go before you can say "Hello, World!" And it runs fast—like, really fast. Need I say more?

Setting Up Your Go Project

Alright, enough chit-chat, let’s get our hands dirty. First, we need to set up a simple Go project. Don’t worry, I’ve got you covered:

  1. Make sure Go is installed. If not, grab it here.

  2. Now, let’s create a project directory and initialize the project:

   mkdir go-rest-api
   cd go-rest-api
   go mod init github.com/yourusername/go-rest-api
Enter fullscreen mode Exit fullscreen mode
  1. Inside this directory, create a new file called main.go, and get ready for some coding magic.

Writing the API

Here’s where things get exciting! We’re going to build a super simple API to manage a list of books (because who doesn’t love books?). Our API will have the following endpoints:

  • GET /books – Fetch all the books (yay, books!)
  • POST /books – Add a new book
  • GET /books/:id – Fetch a specific book by its ID (because not all books are created equal)

Ready? Let’s dive into the code:
Get the gorilla/mux http router using this command:

go get -u github.com/gorilla/mux
Enter fullscreen mode Exit fullscreen mode

In the main.go file:

package main

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "strconv"

    "github.com/gorilla/mux"
)

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

var books []Book

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

func getBook(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    id, err := strconv.Atoi(params["id"])
    if err != nil {
        http.Error(w, "Invalid book ID", http.StatusBadRequest)
        return
    }

    if id == 0 {
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(books)
        return
    }

    // find the book with the given 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)
}

// Add a new book
func createBook(w http.ResponseWriter, r *http.Request) {
    var book Book
    _ = json.NewDecoder(r.Body).Decode(&book)

    if book.Author == "" || book.Title == "" {
        http.Error(w, "Please provide a title and an author", http.StatusBadRequest)
        return
    }

    book.ID = len(books) + 1 // Assign an ID (we’re just winging it here)
    books = append(books, book)
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(book)
}

func main() {
    // Add some dummy data to start with
    books = append(books, Book{ID: 1, Title: "The Go Programming Language", Author: "Alan A. A. Donovan"})
    books = append(books, Book{ID: 2, Title: "Learning Go", Author: "Jon Bodner"})

    // Initialize the router
    r := mux.NewRouter()

    // Define the endpoints
    r.HandleFunc("/books/", getBooks).Methods("GET")
    r.HandleFunc("/books/{id}", getBook).Methods("GET")
    r.HandleFunc("/books", createBook).Methods("POST")

    // Start the server
    fmt.Println("Server is running on port 8000...")
    log.Fatal(http.ListenAndServe(":8000", r))
}
Enter fullscreen mode Exit fullscreen mode

Breaking It Down

  1. Mux Router: We’re using gorilla/mux to handle routing in our API. It makes it easy to define routes and is a go-to for building web services in Go. You can install it with:
   go get -u github.com/gorilla/mux
Enter fullscreen mode Exit fullscreen mode
  1. Handlers: We’ve set up getBooks, getBook, and createBook functions to handle HTTP requests. They use Go’s net/http package to handle responses and data encoding/decoding. Easy-peasy!

  2. JSON Encoding: Go’s built-in json package is doing the heavy lifting here, converting our data into JSON format for easy communication between the client and the API.

Running the API

Now for the fun part—let’s run this thing! In your terminal, simply execute:

go run main.go
Enter fullscreen mode Exit fullscreen mode

Boom! Your API is up and running. You can now use tools like Postman or curl to test it:

  • Get all books:
  curl http://localhost:8000/books
Enter fullscreen mode Exit fullscreen mode
  • Get a specific book:
  curl http://localhost:8000/books/1
Enter fullscreen mode Exit fullscreen mode
  • Add a new book:
  curl -X POST http://localhost:8000/books -d '{"title":"New Book","author":"New Author"}' -H "Content-Type: application/json"
Enter fullscreen mode Exit fullscreen mode

What’s Next?

This little API is just the tip of the iceberg when it comes to what Go can do in backend development. Next week, we’ll level up by adding authentication (yep, we’re going full JWT) and protecting these endpoints from unwanted visitors.

Stay tuned for part 2 -- Setting up middleware for authentication in a REST API using JWT (JSON Web Tokens) in Go

Top comments (2)

Collapse
 
peterkmx profile image
peterkmx

Upvoted ... I would rather say "Go is surprisingly easy to learn" :-) . So far, I did not have time/motivation/challenges/etc... to work on go/golang projects, and yet the code I see in your examples looks familiar. An interesting read, many thanks ... BTW, please have a look at your JWT article, it seems that the content is lost somehow.

Collapse
 
neelp03 profile image
Neel Patel • Edited

Thanks for the upvote! You're absolutely right—Go is surprisingly easy to learn, and I’m glad the examples feel familiar even if you haven’t worked with Go before. That’s one of the reasons why I’m a big fan of it, it just clicks!

As for the JWT article, thanks for the heads-up! I’ll take a look and make sure everything is back in place. Really appreciate the feedback and glad you found the post interesting.