How To Use Templates in Go
Hands-on guide to Go templates: using text/template and html/template, parsing and executing files, range/if pipelines, FuncMap, and safe HTML output.
Drake Nguyen
Founder · System Architect
Introduction
Go templates provide a concise way to render structured text or HTML from Go data structures. The Go standard library ships two template packages: text/template for plain text and html/template for HTML-aware output. Both packages share the same core template engine and syntax, but html/template adds HTML escaping to help prevent XSS when generating web pages.
Prerequisites
- Go installed (use your platform installer or follow the official Go installation guide).
- Familiarity with Go basics: packages, structs, slices, and methods.
- Basic command-line skills to run
go runand edit files.
Importing the template packages
Start a simple program by importing the packages you need. For text output use text/template; for HTML output switch to html/template. You will usually also import os to write output and other utility packages such as strings.
package main
import (
"os"
"text/template" // or "html/template" for HTML output
)
func main() {
// program entry
}
Preparing data for templates
Templates render any Go value, but slices, maps and structs are common. Define a struct to hold the fields you want to present and create a slice to represent multiple items.
type Pet struct {
Name string
Sex string
Intact bool
Age string
Breed string
}
// inside main()
pets := []Pet{
{Name: "Jujube", Sex: "Female", Intact: false, Age: "10 months", Breed: "German Shepherd/Pitbull"},
{Name: "Zephyr", Age: "13 years, 3 months", Sex: "Male", Intact: true, Breed: "German Shepherd/Border Collie"},
}
Parsing and executing templates
To load a template file from disk use template.New combined with ParseFiles. After parsing, call Execute and pass any io.Writer (for example os.Stdout or an open *os.File) plus the data to render.
tmplName := "pets.tmpl"
tmpl, err := template.New(tmplName).ParseFiles(tmplName)
if err != nil {
panic(err)
}
err = tmpl.Execute(os.Stdout, pets)
if err != nil {
panic(err)
}
Basic Go template syntax
Template actions are placed inside double curly braces, for example {{ . }} to refer to the current cursor value. Templates support actions like range, if/else and pipelines that feed data through functions.
Looping with range
Use range to iterate over a slice or map. Inside the loop the dot (.) refers to the current item.
{{ range . }}
---
Name: {{ .Name }}
Sex: {{ .Sex }}
Age: {{ .Age }}
Breed: {{ .Breed }}
{{ end }}
Conditionals (if / else)
If you need reader-friendly output, use if to branch based on fields instead of printing raw booleans. Built-in comparison functions such as eq are available in templates.
Sex: {{ .Sex }} ({{ if .Intact }}intact{{ else }}{{ if eq .Sex "Female" }}spayed{{ else }}neutered{{ end }}{{ end }})
Go template functions and pipelines
Templates include a small set of builtin functions like len, eq, and slice, and you can expose your own Go functions via a template.FuncMap. Pipelines (|) let you chain functions so the result of one call flows into the next.
funcMap := template.FuncMap{
"dec": func(i int) int { return i - 1 },
"replace": strings.ReplaceAll,
}
tmpl, err := template.New("last.tmpl").Funcs(funcMap).ParseFiles("last.tmpl")
Important: call Funcs before parsing files. That makes custom functions like dec or borrowed functions from strings available in the template namespace.
Practical examples
Common scenarios covered by Go templates include:
- Counting items:
{{ . | len }}shows how many elements are in the top-level slice. - Slicing and selecting items: use
slicewith a customdecor arithmetic helper to get last elements. - String transforms: expose
strings.ReplaceAllorstrings.Joinso presentation logic stays in the template.
Rendering HTML safely
When your templates produce HTML, always use html/template instead of text/template. The html/template package escapes input automatically (converting <, >, ", & to entities) to reduce the risk of XSS and broken markup. Function names and template syntax remain the same, so switching is usually a one-line change in the import.
import (
"os"
"html/template" // safe for HTML output
)
// then parse and execute as before; output to a file:
f, err := os.Create("pets.html")
if err != nil { panic(err) }
defer f.Close()
err = tmpl.Execute(f, pets)
Writing template output to files
Any value that implements io.Writer can receive rendered output. Use os.Create to open a file and pass the file handle to Execute. Remember to close the file when finished.
Best practices and tips
- Keep presentation logic in templates and business logic in Go code to maintain separation of concerns.
- Use
html/templatefor HTML to prevent injection, and validate untrusted data on input when possible. - Register utility functions via
FuncMapfor reusable presentation helpers like formatting, joining or trimming. - Favor structured fields (slices for multiple breeds, for example) over brittle single-string formats to simplify templates and searching.
Conclusion
Go templates are a flexible, performant way to render text and HTML from Go programs. Whether you need a compact command-line report or a safe HTML page, the combination of text/template or html/template, template actions (range, if, pipelines), and custom FuncMap functions covers the majority of rendering tasks. For more detail, consult the official package documentation for text/template and html/template and try the small examples above to learn how to use templates in Go.