Dynamic Web using Templates
In the previous post we discussed dynamic websites but using response strings contained in static files. So on this occasion we will try to get to know templating in Golang where the page, say HTML, will be dynamic and can change with the data accessed by the user.
Golang has an HTML template feature which we can use to create dynamic HTML. This feature is found in the html/template
package. Before we use an HTML template, we need to create the template first and then later we will send variables, strings or files so that there is a dynamic part in the HTML template where Golang will use the {{ }}
sign.
Create HTML Templates
When we create a template with a string, we need to tell the name of the template using template text which content we will make dynamic by using the {{.}}
sign. For example like this.
<html>
<body>{{.}}</body>
</html>
To understand better, let’s try just creating an HTML template string like the one below.
func SimpleHTMLTemplateHandler(w http.ResponseWriter, r *http.Request) {
templateText := `<html><body>{{.}}</body></html>`
t, err := template.New("SIMPLE").Parse(templateText)
if err != nil {
panic(err)
}
t.ExecuteTemplate(w, "SIMPLE", "Hello HTML Template")
}
After that, we register our handler function into the mux
handler that we studied previously as below.
...
mux.HandleFunc("/template", SimpleHTMLTemplateHandler)
...
Then we run it and access localhost:8080/template
then a website page will appear displaying the words Hello HTML Template
. This means that our template page is correct and can be accessed in a browser.
Create HTML Templates From Files
Apart from creating templates using strings as previously created, we can also create them directly from files. This makes it easier for us to directly create an HTML file and when we use the file the file name automatically becomes the name of the template. For example, if we have a simple.html
file, the template name is sample.html
.
Let’s try directly to create this HTML template from a file by creating a simple.html
file in the project and in the templates
folder then fill it in as below.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ . }}</title>
</head>
<body>
<h1>{{ . }}</h1>
</body>
</html>
Next, we create another new handler to add an endpoint which can read the HTML template file as below.
func SimpleHTMLFileTemplateHandler(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("./templates/simple.html")
if err != nil {
panic(err)
}
t.ExecuteTemplate(w, "simple.html", "Hello Santekno, HTML File Template")
}
After creating the handler, don’t forget to add or initialize it to the main handleFunc
so that it can be accessed by the URL browser.
...
mux.HandleFunc("/template-file", SimpleHTMLFileTemplateHandler)
...
Run it again and see the results, we can create an HTML template using a template file by sending variables into the HTML so that later we can make the variables dynamic.
Directory Templates
Usually we rarely mention template files one by one, so it’s a good idea to save these templates in one directory. The Golang template already supports the process of loading templates
from directories, making it easier for us not to need to mention the file names one by one.
func TemplateDirectoryHanlder(w http.ResponseWriter, r *http.Request) {
t := template.Must(template.ParseGlob("./templates/*.html"))
t.ExecuteTemplate(w, "simple.html", "Hello Santekno, HTML Directory File Template")
}
Since Golang 1.16 has supported Golang Embed so Golang Embed is recommended for storing template data. By using Golang Embed we no longer need to copy the template file anymore because it is automatically embedded in the distribution file.
// go:embed templates/*.html
var templates embed.FS
func TemplateEmbedHandler(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFS(templates, "templates/*.html")
if err != nil {
panic(err)
}
t.ExecuteTemplate(w, "simple.html", "Hello Santekno, HTML Embed Template")
}
Then don’t forget to also add the mux
handler to additional handler templates that we have created like this.
...
mux.HandleFunc("/template-directory", TemplateDirectoryHanlder)
mux.HandleFunc("/template-embed", TemplateEmbedHandler)
...