How to serve files and process form inputs with Go

in #programming7 years ago (edited)

This short tutorial will be about using Go to serve a file and process the form values submitted from the file using a "POST" action.

golang-gopher-laptop.png

The first step we need to take is create a directory and the files main.go and myform.gtpl inside the directory:

/myform
 - main.go
 - myform.gtpl

Create the contents of myform.gtpl:

<html>
    <head>
    <title></title>
    </head>
    <body>
        <h2 style="text-align: center;">Go lang</h2>
        <form action="/show" method="POST">
            <input type="text" name="task" />
            <button type="submit">Show</button>
        </form>
    </body>
</html>

In the above, you can see the action attribute of the form is assigned the string "/show" and the method is assigned the value "POST". The text input has the name attribute that has "task "assigned to it.

Next inside our main.go file, we import the necessary libraries and create the main function and the show http handler:

package main

import (
    "fmt"
    "net/http"
    "html/template"
)

func show() {}

func main() {}


The main function is where we will register our handler (show) and Go's DefaultServeMux internally (using http.HandleFunc) and listen on the TCP network for incoming connections and call Serve internally (using http.ListenAndServe). We will be serving the files on port 9000:

func main() {
    http.HandleFunc("/show", show);
    http.ListenAndServe(":9000", nil)
}

Then we implement the http handler 'show' in a couple of steps:

Step 1

func show(w http.ResponseWriter, r *http.Request) {
    if r.Method == "GET" {
        t, _ := template.ParseFiles("show.gtpl")
        t.Execute(w, nil)
    }
}

We see in the above that the show handler accepts two parameters, w that is a type of the http.ResponeWriter interface and r that is a type of the *http.Request struct which also has multiple properties such as Method, URL, Header, Body and etc. But, in our case, we are only interested in the Method property for checking if the request is a GET or another type of request such as POST.

If the method is GET, then we invoke ParseFiles on the template and pass into it the name of the file we want and assign the returned value to the variable t. According to the documentation, "ParseFiles is a method that creates a new template and parses the template definitions from the named files". On the template, we invoke Execute(w, nil) to write the output to the IO writer.

Step 2

If the request method is POST, we will need to parse the submitted form and print the value.

The request (r), has the method ParseFrorm(), that will parse the form and populates r.Form and r.PostForm, which are maps on the the r. Then we can do r.Form["task"], to the the value submitted.

func show(w http.ResponseWriter, r *http.Request) {
    if r.Method == "GET" {
        t, _ := template.ParseFiles("show.gtpl")
        t.Execute(w, nil)
    } else {
        r.ParseForm()
        fmt.Println(r.Form["task"])
    }
}

In conclusion, serving a file in Go is very simple; you only need two basic libraries ("html/template" and "net/http"). for accomplishing that task. In addition, you need to understand the http object, and the http.ResponseWriter interface and *http.Request struct and the properties they contain (such as Method in the case of *http.Request). You also need to understand how to parse files (know what the r.ParseFiles("fileName") method does), and the use of r.ParseForm() and how it populates r.Form.

Here is the entire go code, without breaking it into snippets:

package main

import (
    "fmt"
    "html/template"
    "net/http"
)

func show(w http.ResponseWriter, r *http.Request) {
    if r.Method == "GET" {
        t, _ := template.ParseFiles("show.gtpl")
        t.Execute(w, nil)
    } else {
        r.ParseForm()
        fmt.Println(r.Form["task"])
    }
}

func main() {
    http.HandleFunc("/show", show);
    http.ListenAndServe(":9000", nil)
}

References:

https://golang.org/pkg/net/http/
https://golang.org/pkg/html/template/#Template.Execute
https://astaxie.gitbooks.io/build-web-application-with-golang/en/