Your First HTTP Server in GO

We already know why to choose GO over Python, therefore today I’ll show an example of a simple GO HTTP Server project in Visual Studio Code.

VSCode is a lightweight and super popular editor for multidisciplinary developers and DevOps. I suggest to use VSCode for GO development, it has GO plugin that helps to configure, debug and test your code.

Our simple HTTP server will actually do only two simple operations: 

  1. It will show some object in the browser
  2. It will save new provided object as JSON file

So let’s create a project folder, I named it go-http. Right under go-http I another folder books

Now let’s define our module. Run this command in terminal: > go mod init books

Right after that you will see in the explorer that new file go.mod has been created. This file defines our module. If you open it you will see following:

module books

go 1.15

The go.mod file defines the module’s module path, which is also the import path used for the root directory, and its dependency requirements, which are the other modules needed for a successful build. This file is crucial for VSCode code references detection and proper highlighting etc.

Let’s create a JSON file which will represent our book objects:

[
    {
        "id": "12345",
        "title": "Consider Yourself Dead",
        "author": "James Hadley Chase",
        "year": "1978"
    },
    {
        "id": "123412",
        "title": "The Crime in Cabin 66",
        "author": "Agatha Christie",
        "year": "1943"
    }
]

We can finally start writing code 🙂

Create new file books.go under books directory:

package main

import (
    "encoding/json"
    "io/ioutil"
)

type book struct {
    Id     string `json:"id"`
    Title  string `json:"title"`
    Author string `json:"author"`
    Year   string `json:"year"`
}

func getBooks() (books []book) {

    fileBytes, err := ioutil.ReadFile("./books.json")

    if err != nil {
        panic(err)
    }

    err = json.Unmarshal(fileBytes, &books)

    if err != nil {
        panic(err)
    }

    return books
}

func saveBooks(books []book) {
    bookBytes, err := json.Marshal(books)
    if err != nil {
        panic(err)
    }

    err = ioutil.WriteFile("./new-books.json", bookBytes, 0644)
    if err != nil {
        panic(err)
    }

}

Here we created a struct that represents a book object and two simple methods – one for fetching books and another one for saving a new list of books if provided.

The only thing that left to do is to write our main file that will start HTTP server. Thanks to the brevity of GO it’s very easy task to do:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {

    http.HandleFunc("/", GetBooksHandler)
    http.HandleFunc("/save", SaveBooksHandler)

    http.ListenAndServe(":8080", nil)
}

func GetBooksHandler(w http.ResponseWriter, r *http.Request) {

    books := getBooks()

    bookBytes, err := json.Marshal(books)

    if err != nil {
        panic(err)
    }

    w.Write(bookBytes)
}

func SaveBooksHandler(w http.ResponseWriter, r *http.Request) {

    if r.Method == "POST" {

        body, err := ioutil.ReadAll(r.Body)
        if err != nil {
            panic(err)
        }

        var books []book
        err = json.Unmarshal(body, &books)
        if err != nil {
            w.WriteHeader(400)
            fmt.Fprintf(w, "Bad request!")
        }

        saveBooks(books)

    } else {
        w.WriteHeader(405)
        fmt.Fprintf(w, "Method not Supported!")
    }
}

So our main() contains only three lines of code where we defining handlers for GET and POST actions and the last line starts the server.

GetBooksHandler() reads the books.json and translates it to bytes and writes it to the response.

SaveBooksHandler() performs the opposite action – it reads the body of the request, transforms it to JSON and finally saves it.

In order to run our server first we need to build the code. Run following commands in terminal:

cd books
go build

We’re ready to run the server! If you’ll look into your project file structure you’ll see there is new binary file under books directory. Just run it: > ./books

Go to your browser, type localhost:8080/ and you should see the content of our famous books.json

In order to send POST request to our server we can use Postman or similar tool:

Select POST, type in address (http://localhost:8080/save) then write some new JSON in the body of request and click Send.

If you’ll go to the project file structure and you should see new-books.json file under books directory.

This is pretty it, you are welcome to download the source code from here.

I also added Dockerfile to the project that allows to run our server inside docker container.

Please write your questions/suggestions in the comments section.

Happy coding!

1 COMMENT

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.