Go: Templates
Is it just me? I can never remember how to use html/template
in Go and I can never make sense of the docs either, which I feel are
accurate but present the material in essentially random order. Here’s
the cheat sheet.
A Template
is a
tree of templates
The most important thing to understand about Go templates is that a
Template
is not necessarily a single template, but
potentially a whole tree of templates that can have other associated
templates. All the API weirdness of text/template
, namely
that you can’t just load a template into a variable but must also give
it another name with New()
, flows from this fact. Without
knowing this, the New()
function’s naming requirement makes
no sense.
This ought to be the first thing you learn, but it’s buried in a
minor section of the text/template
docs halfway down the
page, after you’ve covered such things as multi-way equality tests in
the template language’s boolean operators. See associated
templates.
Loading a template
The awkwardness of
New()
template.New("file.html").ParseFiles("file.html")
If you’re loading a single template from a file, this gets awkward.
You may want to give your template a memorable name, a reasonable thing
to want. But the argument to New()
has to be the same as
the actual filename, or else you get errors (“error: template: […] is an
incomplete or empty template”).
You can just use
ParseFiles
template.ParseFiles("file.html") // victory
The docs almost go out of their way to hide that these functions
exist in the package, because ParseFiles()
and friends are
listed under “Types” > “type Template
” with the methods
of Template
, instead of under “Functions”, where all the
other non-method functions are listed.
Anyways, use them and you get the same result as if you had used
New(filename).ParseFiles(filename)
.
Load templates from an embedded FS
//go:embed dir
var _dir embed.FS
template.ParseFS(fs, "file.html")
You can load templates from an embed.FS
using
ParseFS
instead of ParseFiles
.
(Yes, there has to be no space in //go:embed
or else it
doesn’t work.)
Executing a template
You can execute a template from code, or from within another template.
From code
t.Execute(writer, data)
writer
is an io.Writer
and thus can be an
http.ResponseWriter
.
From another template
{{template "name" pipeline}}