In the html/template
(and text/template
) packages, template.New
has the following signature:
func New(name string) *Template
What exactly is the name
used for? I've scanned the docs (and a bit of source), but to no avail. I just instantiate all of my templates with an empty string and it doesn't seem to make a difference. Why should I bother with a name?
Even for naming templates, the two seem equivalent:
template.Must(template.New("").Parse(`{{ define "body" }}Body{{ end }}`)) template.Must(template.New("body").Parse(`Body`))
https://play.golang.org/p/wKzCHdLf2S
Go's template is designed to be extended by developers, and provides access to data objects and additional functions that are passed into the template engine programmatically. This tutorial only uses functions universally provided in the text/template package, and does not discuss the specifics of data access.
HTML/template is a Golang (Go) package that implements data-driven templates for generating HTML outputs that are safe against code injection. A key benefit of using HTML/template is that it produces safe, escaped HTML output using contextual auto-escaping.
Go templates are a powerful method to customize output however you want, whether you're creating a web page, sending an e-mail, working with Buffalo, Go-Hugo, or just using some CLI such as kubectl. There're two packages operating with templates — text/template and html/template .
The name of the template–unsurprisingly–is to name the template.
What is it good for? As long as you don't want to refer to the template, it doesn't really matter. But if you want to refer to it, then yes, you refer to it by its name.
When would you want to refer to it? When you want to include a template in another e.g. using the {{template}}
action, or when you want to execute a specific template using Template.ExecuteTemplate()
.
So far so good, but there's still a missing key point. This is not unambiguous / trivial: a template.Template
value is "the representation of a parsed template". But the wording here is a little "imperfect". A template.Template
value may be (and usually is) a collection of multiple, associated templates. template.Template
has an unexported field:
tmpl map[string]*Template // Map from name to defined templates.
This tmpl
field holds all other associated templates, templates that are visible to the template, and which can be referred to–yes–by their names.
When you parse multiple templates at once, using Template.ParseFiles()
or Template.ParseGlob()
, then the templates will be named by the file names, and they will be associated automatically (the above mentioned functions return a single template.Template
value, which holds all the parsed templates, associated). Doc of Template.ParseFiles()
is clear on this:
ParseFiles creates a new Template and parses the template definitions from the named files. The returned template's name will have the base name and parsed contents of the first file. [...]
When parsing multiple files with the same name in different directories, the last one mentioned will be the one that results. For instance, ParseFiles("a/foo", "b/foo") stores "b/foo" as the template named "foo", while "a/foo" is unavailable.
The template name can come from multiple places:
{{define "somename"}}
or {{block "somename"}}
actions),template.New()
(function) or Template.New()
(method).Let's see some examples:
func main() { t := template.Must(template.New("one").Parse(t1src)) template.Must(t.New("other").Parse(t2src)) // error checks omitted for brevity // Executes default, "one": t.Execute(os.Stdout, nil) // Executes explicit, "one": t.ExecuteTemplate(os.Stdout, "one", nil) // Executes explicit, "other": t.ExecuteTemplate(os.Stdout, "other", nil) } const t1src = `I'm some template. ` const t2src = `I'm some OTHER template. `
Output (try it on the Go Playground):
I'm some template. I'm some template. I'm some OTHER template.
If you now go ahead, and change the first 2 lines to this:
t := template.Must(template.New("one").Parse(t1src)) t = template.Must(t.New("other").Parse(t2src))
Then what happens here is that we assigned a new template.Template
value to t
, which was the result of parsing t2src
, so that will be the default, but still both templates can be "reached" from it as they are associated. The output changes to this (try it on the Go Playground):
I'm some OTHER template. I'm some template. I'm some OTHER template.
Calling template.New()
(function) creates a new template, associated to none. When calling Template.New()
(method), the returned template will be associated with (all) the template(s) the method is called on.
Now let's see some examples regarding "embedded" templates.
func main() { t := template.Must(template.New("one").Parse(t1src)) template.Must(t.New("other").Parse(t2src)) template.Must(t.New("third").Parse(t3src)) t.Execute(os.Stdout, nil) t.ExecuteTemplate(os.Stdout, "one", nil) t.ExecuteTemplate(os.Stdout, "other", nil) t.ExecuteTemplate(os.Stdout, "embedded", nil) t.ExecuteTemplate(os.Stdout, "third", nil) } const t1src = `I'm some template. {{block "embedded" .}}I'm embedded in "one". {{end}}` const t2src = `I'm some OTHER template. ` const t3src = `I'm the 3rd, including everything from "one": {{template "one"}} `
Output (try it on the Go Playground):
I'm some template. I'm embedded in "one". I'm some template. I'm embedded in "one". I'm some OTHER template. I'm embedded in "one". I'm the 3rd, including everything from "one": I'm some template. I'm embedded in "one".
It should be obvious now what the role of the template name is, and where it comes from.
It is used to render associated templates.
For instance:
tmpl := template.Must(template.New("body").Parse(` {{ define "body" }} Body {{ end }} `)) tmpl = template.Must(tmpl.New("base").Parse(` Start of base template {{ template "body" }} End of base template `)) tmpl = template.Must(tmpl.New("baz").Parse(` Start of baz template {{ template "body" }} End of baz template `)) tmpl.ExecuteTemplate(os.Stdout, "base", nil) tmpl.ExecuteTemplate(os.Stdout, "baz", nil)
Play Example
Output:
Start of base template Body End of base template Start of baz template Body End of baz template
tmpl.ExecuteTemplate(os.Stdout, "base", nil)
will render the template using the "base" template
tmpl.ExecuteTemplate(os.Stdout, "baz", nil)
will render the template using the "baz" template
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With