Web Development Tutorial

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

3 min read
How To Use Templates in Go
How To Use Templates in Go

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 run and 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 slice with a custom dec or arithmetic helper to get last elements.
  • String transforms: expose strings.ReplaceAll or strings.Join so 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/template for HTML to prevent injection, and validate untrusted data on input when possible.
  • Register utility functions via FuncMap for 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.

Stay updated with Netalith

Get coding resources, product updates, and special offers directly in your inbox.