Go Parsing Templates

By: Stephen Patrick | 11 Sep 2016 | Category: Go Template Engine

Go Parsing Templates

As mentioned previously Go provides a template engine that allows us to create template files containing text content which can be rendered as html content. This functionality is provided by the html/template package. Normally, when we wish to create a template we use one of the parse functions of the html/template package.

Go: Parse Template From String

We can create a template from a string by first creating a new template and calling the Parse function.

package templates

import (
   "bytes"
    "html/template"
)

func parseStrToStr(templateStr string, data interface{}) (string,error) {
   t := template.New("fromString")
   t, err := t.Parse(templateStr)

   if err !=nil {
       return "", err
   }

   var buffer bytes.Buffer
   t.Execute(&buffer, data)
   return buffer.String(), nil
}

Above we create a new template by calling the new function and passing the template name. We then call the parse method to parse the template. If an error is returned we return an empty string along with the error to the caller. Next we create a byte buffer to hold the result of executing the template by calling the Execute method.

Below we show our test from the file parse_test.go that was used to drive and test the above code.

package templates
import (
   "testing"
)

func TestParseStrToStr(t *testing.T) {
   expected := `<p>This is a paragraph</p>`
   result, err := parseStrToStr("<p>This is a paragraph</p>", nil)
   if err !=nil {
       t.Fatal("Expected no error")
   }

   if expected != result {
       t.Errorf("Expected output did not match Expected: %s but Got: %s",expected, result)
   }
}

Go: Parse Template From Files

We can also create a template from a number of template files by using the ParseFiles function. When we call the ParseFiles method Go will return an new struct object if parsing was successful. We can then use the template object within our code.

func parseFilesToStr(data interface{}, filenames ... string) (string,error) {
   t, err := template.ParseFiles(filenames)
   if err !=nil {
       return "", err
   }

   var buffer bytes.Buffer
   t.Execute(&buffer, data)
   return buffer.String(), nil
}

Above we create a new function that takes the template arguments as the data parameter, and templates to parse. This function will return a string consisting of the rendered template content. We call the template.ParseFiles function, to parse the template files. This function is a variadic function as it can take a variable number of templates. What is interesting about this method is that we can pass in any number of templates. However, only one template is returned for us to work with. The other templates are added as a map of templates. These templates can then be used later facilitating template includes.

Again we have a test that was used to drive the code.

func TestParseFilesToStr(t *testing.T) {
   expected := `<!DOCTYPE html>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <title>Go HTML Templates</title>
</head>
<body>
 Hello World!
</body>
</html>`

   result, err := parseFilesToStr("Hello World!", "./resources/helloworld.html")

   if err !=nil {
       t.Fatal("Expected no error")
   }

   if strings.TrimSpace(expected) != strings.TrimSpace(result) {
       t.Errorf("Expected output did not match Expected: %s but Got: %s",expected, result)
   }
}

Go: Parse Template Using A Pattern

We can also create templates by matching templates using a pattern using the ParseGlob function.

func parseGlobToStr(data interface{}, pattern string) (string,error) {
   t, err := template.ParseGlob(pattern)
   if err !=nil {
       return "", err
   }

   var buffer bytes.Buffer
   t.Execute(&buffer, data)
   return buffer.String(), nil
}

The ParseGlob function takes a pattern and searches for matching templates with the given pattern. The test used to drive the code is shown below.

func TestParseGlobToStr(t *testing.T) {
   expected := `<!DOCTYPE html>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <title>Go HTML Templates</title>
</head>
<body>
 Hello World!
</body>
</html>`

   result, err := parseGlobToStr("Hello World!", "./resources/*.html")

   if err !=nil {
       t.Fatal("Expected no error")
   }

   if strings.TrimSpace(expected) != strings.TrimSpace(result) {
       t.Errorf("Expected output did not match Expected: %s but Got: %s",expected, result)
   }
}

Go: Template Parse Error Handling

In the previous examples we tested for an error, and if an error was found we returned it to the caller. There are a couple of ways to structure our code to deal with errors. However, the template package also provides a Must function. The intention of this method is to ensure a template is always parsed. If an error occurs during parsing the code produces a panic. The Must function wraps a function that returns a pointer to a template for example:

t:= template.Must(template.template.ParseFiles(filenames))

The code for this examples can be found here.