Go Templates Tutorial
Go's template packages (text/template and html/template) provide powerful tools for generating dynamic content. This tutorial covers template syntax, actions, functions and security considerations.
1. Basic Templates
1.1 Creating and Executing Templates
The simplest template example with variable substitution:
package main
import (
"os"
"text/template"
)
func main() {
// Define template
tmpl := `Hello, {{.Name}}! Today is {{.Day}}.`
// Create template object
t := template.Must(template.New("greeting").Parse(tmpl))
// Execute with data
data := struct {
Name string
Day string
}{
Name: "Alice",
Day: "Monday",
}
t.Execute(os.Stdout, data)
}
Key Concepts:
- {{.Field}}: Accesses data fields
- template.New(): Creates new template
- Parse(): Compiles template text
- Execute(): Renders template with data
2. Template Actions
2.1 Conditionals
Control template flow with if/else statements:
const tmpl = `
{{if .User.IsAdmin}}
<p>Welcome ADMIN {{.User.Name}}</p>
{{else if .User.IsLoggedIn}}
<p>Welcome back {{.User.Name}}</p>
{{else}}
<p>Please log in</p>
{{end}}`
2.2 Loops
Iterate over slices, arrays and maps:
const tmpl = `
<ul>
{{range .Items}}
<li>{{.}}</li>
{{else}}
<li>No items found</li>
{{end}}
</ul>`
Range Features:
- {{range .}}: Iterates over collection
- {{.}}: Current item in loop
- {{else}}: Executes if collection empty
3. Template Functions
3.1 Built-in Functions
Go templates include useful built-in functions:
const tmpl = `
{{len .Items}} items total
{{index .Names 2}} is the 3rd name
{{printf "Price: $%.2f" .Price}}
{{html "<script>alert()</script>"}}`
3.2 Custom Functions
Extend templates with your own functions:
func main() {
funcMap := template.FuncMap{
"uppercase": strings.ToUpper,
"add": func(a, b int) int { return a + b },
}
t := template.Must(
template.New("").Funcs(funcMap).Parse(
`{{uppercase .Name}} ({{add .A .B}})`,
),
)
t.Execute(os.Stdout, map[string]interface{}{
"Name": "hello",
"A": 5,
"B": 3,
})
}
4. HTML Templates
4.1 Auto-escaping
The html/template package automatically escapes content:
package main
import (
"html/template"
"os"
)
func main() {
const tpl = `
<h1>{{.Title}}</h1>
<p>{{.Content}}</p>`
t := template.Must(template.New("webpage").Parse(tpl))
data := struct {
Title string
Content string
}{
Title: "My Page",
Content: "<script>alert('xss')</script>",
}
t.Execute(os.Stdout, data)
}
Security Features:
- Automatic HTML escaping
- Context-aware sanitization
- Safe against XSS attacks
5. Template Inheritance
5.1 Base Templates
Create reusable template layouts with blocks:
// base.html
{{define "base"}}
<html>
<head>
<title>{{block "title" .}}Default Title{{end}}</title>
</head>
<body>
{{block "content" .}}Default content{{end}}
</body>
</html>
{{end}}
// page.html
{{define "title"}}My Page{{end}}
{{define "content"}}
<h1>Welcome</h1>
<p>Page content here</p>
{{end}}`
5.2 Template Composition
Combine templates using the template action:
func main() {
// Parse all template files
t := template.Must(template.ParseFiles("base.html", "page.html"))
// Execute specific template
t.ExecuteTemplate(os.Stdout, "base", nil)
}
6. Best Practices
6.1 Template Organization
- Keep templates in separate
.tmplfiles - Use a
templatesdirectory - Group related templates together
6.2 Error Handling
// Proper template initialization
t, err := template.New("email").Parse(tmpl)
if err != nil {
log.Fatalf("Failed to parse template: %v", err)
}
// Safe execution
err = t.Execute(os.Stdout, data)
if err != nil {
log.Printf("Template execution failed: %v", err)
}
6.3 Performance Considerations
// Parse templates once at startup
var templates = template.Must(template.ParseGlob("templates/*.tmpl"))
// Then reuse the parsed templates
func renderTemplate(w http.ResponseWriter, name string, data interface{}) {
err := templates.ExecuteTemplate(w, name+".tmpl", data)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
×