Templates 03 - Nested Templates
Nested Templates
We can nest templates in Go, allowing us to create smaller parts of a template, similar to components.
In this example, we will use three files: header.tmpl, body.tmpl, and footer.tmpl, here is the content of the files:
Header
{{ define "Header" }}
Report: {{ .ReportName }} --- Year: {{ .ReportYear }}{{ "\n" }}
------------------------------------------------------------{{ "\n" }}
{{- end }}
We declare a new template using the {{ define “TemplateName” }} tag and need to close it with {{ end }}.
Footer
{{ define "footer" -}}
------------------------------------------------------------{{ "\n" }}
Report User: {{ .ReportUser }}
{{ end }}
The footer template is very similar to the header template.
Body
The body template contains the most new information compared to the other templates.
{{ define "body" }}
{{ template "Header" . }}
{{- range .Users -}}
Name:{{ .Name }} LastName: {{ .LastName }}{{ "\n" }}
{{- end -}}
{{ template "footer" . }}
{{ end }}
Just like we declared the header and footer templates, we also need to declare the body template.
We can use the templates created earlier with the template function, followed by the name of the template we want to use.
Pay close attention to the . after the template name. This . is not mandatory, but by using it, we are passing the data sent to the body template to the header template.
Another change is that the struct passed to the template is now like this:
type Report struct {
ReportName string
ReportYear string
ReportUser string
Users []User
}
type User struct {
Name string
LastName string
Country string
Admin bool
YearsOfExperience int
}
The Report struct will be passed to the template, which is why the range is done on the Users field.
This is our code snippet that executes the template:
type Report struct {
ReportName string
ReportYear string
ReportUser string
Users []User
}
type User struct {
Name string
LastName string
Country string
Admin bool
YearsOfExperience int
}
func main() {
tmplFiles := []string{"header.tmpl", "body.tmpl", "footer.tmpl"}
users := []User{
{"John", "Doe", "USA", true, 25},
{"Gavin", "Steele", "USA", false, 3},
{"Ashton", "Walsh", "CA", false, 5},
}
report := Report{
ReportName: "Sales",
ReportYear: "2025",
ReportUser: "Goku",
Users: users,
}
tmpl, err := template.New("myReport").ParseFiles(tmplFiles...)
if err != nil {
panic(err)
}
err = tmpl.ExecuteTemplate(os.Stdout, "body", report)
if err != nil {
panic(err)
}
}
We need to parse all the files that we referenced in the main body template.
ow we will use the ExecuteTemplate function, passing the standard output, the template that should be loaded since we parsed 3 files, and we also need to pass the data that will be used in the execution.
This is the result:
Report: Sales --- Year: 2025
------------------------------------------------------------
Name:John LastName: Doe
Name:Gavin LastName: Steele
Name:Ashton LastName: Walsh
------------------------------------------------------------
Report User: Goku