How to Generate HTML with Golang Templates

An example of how to use Go templates for generating an HTML page

Photo by Pankaj Patel on Unsplash

Here, I present another example that I made to follow up on my previous article on “How to use templates in Golang”. I’ll be using some of the basic techniques on using Golang (Go Language) templates from that article. In addition to this project, I also decided to use nested templates and write my own simple functions for use inside the templates.

As this was an exercise in using Golang templates and not in web design, I decided to look for an existing page design. Hence, all images, CSS, and JS are verbatim from Mr.Web Designer’s video tutorial (the code is free to use). The HTML from the tutorial, on the other hand, has obviously been adapted for use in the templates.

Here, you can see the webpage that we’ll be generating, given product data:

The webpage is responsive, so it adapts to different screen widths, and when you click on one of the ‘products’, you get a pop-up with a description and some buttons.

In the original example from Mr. Web Designer, the products and their descriptions were hard-coded in the HTML file. Using templates and rendering them with (different) data can avoid hard-coding the products and their descriptions.

In what follows, I will first show you the actual program that will parse and render the templates and then output the generated HTML file. After that, I will show you what the different templates look like and discuss some of the techniques I have used in them.

Here is the Golang program that will do all the work:

In lines 3–8, we import the necessary packages. The packages bufio , bytes and os are needed for outputting the HTML file. The package html/template is used for dealing with the templates.

In lines 10–17, we define product which is a struct for holding the product data. Make sure that all the properties are written with capitals, ie, that they are exportable. This is required when using a struct inside Golang templates.

Also, note that the number of stars is a floating-point number between 0 and 5. The reason we use a type of float64 for this number is that the templates use float64 for all floating-point numbers.

In lines 19–25, I created two functions because I was not satisfied with the ones provided by the sprig package. The first function called subtr()is a simple subtraction function for floating-point numbers, and the second function called list()is used to create a list of floating-point numbers.

In lines 29–36, we define the data to be rendered in the templates. In this example, the data is hardcoded. In a more realistic setting, this data would probably be stored in a database of some kind. Note that the data follows the definition of the product struct.

In line 38, we add the file names of all the templates to a slice.

In lines 40–43, the directory name /templates/ is added to all the filenames.

In line 45, we parse the templates with ParseFiles()make sure to add the two functions subtr and list using template.FuncMap{}and check the correctness of the templates with template.Must().

In lines 47–48, we render the templates to a byte buffer. To make sure that the renderer starts with the page template we use ExecuteTemplates() with "page" as an argument. Here, we also supply the data that we have defined to the renderer.

In lines 50–54, the rendered byte buffer is output to an HTML file called index.htmlin the ./static directory.

Here I discuss all the templates used for this project.

The “page” template

This is the template that defines a complete webpage. It calls three other templates; header, contentand footer.

In line 1, it is essential to define page inside this template, otherwise ExecuteTemplates() will not find it.

In line 3, note that a dot is added when the content template is called. This signals to the template renderer that the data supplied is to be sent along to the content template. This is the same as providing parameters to a function. Given that the header and footer templates don’t need the data; there is also no need to add the dot.

The “header” template

This template is used to render a typical HTML header that loads fonts, styles, and JavaScript code.

Note that we use the define and end keywords to define the template as the header template.

Also, note the ‘-‘ sign before the double ending brackets. This sign tells the renderer to remove whitespace and newlines. From my experience, you’ll need to experiment with the placement of these ‘-‘s.

To achieve the desired output, you sometimes need to put the ‘-‘s after the beginning double brackets, sometimes before the double ending brackets, and sometimes in both places.

The “content” template

This is the template that renders the body of the HTML file.

A reason for defining the content separately from the header and footer is that we can quickly create other pages with different content but with the same header and footer—ie, loading the same CSS, JS, fonts, etc.

As mentioned before, I created my own versions of the Sprig list and subffunctions, as I wasn’t happy with the ones in that package. This was because I got some errors that I couldn’t get rid of. I also decided to call my subtraction function subtr instead of subf.

In lines 5–12, we loop over all the products in our data. For each product, we create the internal template variables $index and $item. We use the $index for the data-name attribute. From $item we extract the Img, Nameand Price properties for use in the HTML.

In lines 16–42, we do the same as above, but we also extract the $Stars $Description and $Reviews properties from the $item.

In addition, in line 22, we create a list called $stars. This list contains floating-point numbers from 1.0 to 5.0. We’ll be needing these to display the stars. These numbers represent the threshold value for displaying each star.

Then, in lines 23–32, we create a loop to display the stars. Essentially we have three types of stars that we can show: full stars, half stars, and empty stars.

Using conditionals, we determine whether the number of stars of an item ($item.Stars) is less than the star number from the $starslist minus 0.5, or less than the star number, or higher. In the first case, we display an empty star. In the second case, we display a half star. Finally, in the last case, we display a full star.

The “footer” template

Nothing special happens here except defining the template as footer.

Leave a Comment