How to serve files and process form inputs with Go
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.
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/