How to Create Plaintext Reports in Go Using Templates with Loops and Conditionals

Alissa LozhkinAlissa Lozhkin
3 min read

My previous blog post introduced templates in Go by demoing how to produce a simple string using the template.New().Parse function. In this blog post, I will go over the steps on how to use the text/template package with loops and conditional logic to produce a plaintext report. This demo will be using the template.New().ParseFiles function.

First off, we introduce a feature of templates called actions. An action, defined as {{ <action> }}, may be a for-loop, conditional statement, or even a custom function defined by the user. Using the same starter code as in the last post, we have:

package main

import (
    "os"
    "text/template"
)

type Person struct {
    Name       string
    Age        int
    Employed   bool
    Occupation string
}

func main() {
    // insert code here
}

Note that whenever we want to export a variable or a function in Go, the variable name must begin with a capital letter. Hence, the Person struct and all of its attributes begin with capital letters.

The next step is to create a template file which we will call demo.tmpl. For now, this file will contain some basic text:

Nothing here yet

In main.go, we create a slice containing a couple of Person objects, which we will then pass to the template file by calling template.Execute.

func main() {
    people := []Person{
        {
            Name:       "Bob",
            Age:        42,
            Employed:   true,
            Occupation: "Doctor",
        },
        {
            Name:       "Jessica",
            Age:        22,
            Employed:   false,
            Occupation: "",
        },
    }
}

In the same file, we then call template.New().ParseFiles. This function initializes a template with the filename demo.tmpl and parses it to ensure that there are no syntax errors. The panic function ensures quick error-handling. We then execute the template using template.Execute, with the slice people as the second argument, as can be seen below:

    tmplFile := "demo.tmpl"
    tmpl, err := template.New(tmplFile).ParseFiles(tmplFile)
    if err != nil {
        panic(err)
    }
    err = tmpl.Execute(os.Stdout, people)
    if err != nil {
        panic(err)
    }

If we run go run main.go, on the terminal will be printed the string nothing here yet, as there is nothing else in the template file at the moment.

We therefore begin populating the template file. We can use the range action to iterate through the slice that was passed in.

{{ range . }}
-----------------
Name: {{.Name}}
Age: {{.Age}}
{{ end }}

In the command {{ range . }}, the . represents the slice. The range action is also terminated with {{ end }}. In the code block above, we access the name and age of each Person object in the people slice. Running go run main.go gives us the following result:

-----------------
Name: Bob
Age: 42

-----------------
Name: Jessica
Age: 22

We want to display the occupation of each Person conditionally: if Employed is true, then display the occupation, otherwise display Unemployed. Both the if and else actions are used for this as seen below:

{{ range . }}
-----------------
Name: {{.Name}}
Age: {{.Age}}
Occupation: {{ if .Employed }}{{ .Occupation }}{{ else }}Unemployed{{end}}
{{ end }}

Note that the conditional statement is also terminated with {{ end }}. Running go run main.go gives us the following result:

-----------------
Name: Bob
Age: 42
Occupation: Doctor

-----------------
Name: Jessica
Age: 22
Occupation: Unemployed

At the top of the file, we want to include the number of people contained in the slice. We can do so by using the len action like so:

People: {{ len . -}}
{{ range . }}
-----------------
Name: {{.Name}}
Age: {{.Age}}
Occupation: {{ if .Employed }}{{ .Occupation }}{{ else }}Unemployed{{end}}
{{ end }}

Note that in the command {{ len . -}}, the . represents the slice and the - indicates that a newline character \n should not be printed after the first line. Running go run main.go gives us the final result:

People: 2
-----------------
Name: Bob
Age: 42
Occupation: Doctor

-----------------
Name: Jessica
Age: 22
Occupation: Unemployed
0
Subscribe to my newsletter

Read articles from Alissa Lozhkin directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Alissa Lozhkin
Alissa Lozhkin

My name is Alissa and I am a fourth-year computer science and math student at the University of Toronto! I am very interested in computer science and software development, and I love learning about new technologies! Get in touch with me on LinkedIn: https://www.linkedin.com/in/alissa-lozhkin