Introduction
Go’s text/template
package provides powerful tools for creating and executing templates. Templates allow you to generate text dynamically by combining static content with data. This is particularly useful for generating HTML, email content, configuration files, and other types of structured text. In this chapter, you will learn the basics of using text templates in Go, including defining templates, passing data to templates, and using template functions.
Basic Usage
Defining and Executing a Template
To define and execute a basic template, you create a template.Template
object, define the template content, and then execute the template with data.
Example:
package main
import (
"os"
"text/template"
)
func main() {
// Define a template
tmpl := `Hello, {{.Name}}!`
// Create a new template and parse the content
t := template.Must(template.New("example").Parse(tmpl))
// Define data to pass to the template
data := struct {
Name string
}{
Name: "Alice",
}
// Execute the template with the data and write the output to stdout
t.Execute(os.Stdout, data)
}
In this example, a simple template is defined with a placeholder for the Name
field. The template.Must
function ensures that the template is parsed correctly, and t.Execute
executes the template with the provided data.
Passing Data to Templates
You can pass various types of data to templates, including structs, maps, and slices.
Example: Passing a Struct
package main
import (
"os"
"text/template"
)
type Person struct {
Name string
Age int
}
func main() {
tmpl := `Name: {{.Name}}, Age: {{.Age}}`
t := template.Must(template.New("example").Parse(tmpl))
person := Person{
Name: "Bob",
Age: 30,
}
t.Execute(os.Stdout, person)
}
In this example, a Person
struct is passed to the template, which uses the Name
and Age
fields.
Example: Passing a Map
package main
import (
"os"
"text/template"
)
func main() {
tmpl := `Name: {{.Name}}, Age: {{.Age}}`
t := template.Must(template.New("example").Parse(tmpl))
data := map[string]interface{}{
"Name": "Carol",
"Age": 25,
}
t.Execute(os.Stdout, data)
}
In this example, a map is passed to the template, which uses the Name
and Age
keys.
Control Structures
Templates support control structures like if
, range
, and with
.
Example: If Statement
package main
import (
"os"
"text/template"
)
func main() {
tmpl := `{{if .IsAdmin}}Welcome, admin!{{else}}Welcome, user!{{end}}`
t := template.Must(template.New("example").Parse(tmpl))
data := struct {
IsAdmin bool
}{
IsAdmin: true,
}
t.Execute(os.Stdout, data)
}
In this example, the if
statement is used to conditionally display different messages based on the IsAdmin
field.
Example: Range Statement
package main
import (
"os"
"text/template"
)
func main() {
tmpl := `{{range .}}Name: {{.Name}}, Age: {{.Age}}
{{end}}`
t := template.Must(template.New("example").Parse(tmpl))
people := []struct {
Name string
Age int
}{
{"Dave", 40},
{"Eve", 35},
}
t.Execute(os.Stdout, people)
}
In this example, the range
statement is used to iterate over a slice of structs and display their fields.
Example: With Statement
package main
import (
"os"
"text/template"
)
func main() {
tmpl := `{{with .Address}}City: {{.City}}, State: {{.State}}{{end}}`
t := template.Must(template.New("example").Parse(tmpl))
data := struct {
Name string
Address struct {
City string
State string
}
}{
Name: "Frank",
Address: struct {
City string
State string
}{
City: "New York",
State: "NY",
},
}
t.Execute(os.Stdout, data)
}
In this example, the with
statement is used to simplify access to the Address
field within the template.
Template Functions
You can use built-in template functions or define custom functions to extend template capabilities.
Example: Built-In Functions
package main
import (
"os"
"text/template"
)
func main() {
tmpl := `{{len .Names}} names: {{join .Names ", "}}`
funcMap := template.FuncMap{
"join": strings.Join,
}
t := template.Must(template.New("example").Funcs(funcMap).Parse(tmpl))
data := struct {
Names []string
}{
Names: []string{"George", "Helen", "Ian"},
}
t.Execute(os.Stdout, data)
}
In this example, the built-in len
function is used to get the length of a slice, and the custom join
function is used to join slice elements.
Example: Custom Functions
package main
import (
"os"
"strings"
"text/template"
)
func main() {
tmpl := `{{upper .Name}}`
funcMap := template.FuncMap{
"upper": strings.ToUpper,
}
t := template.Must(template.New("example").Funcs(funcMap).Parse(tmpl))
data := struct {
Name string
}{
Name: "john",
}
t.Execute(os.Stdout, data)
}
In this example, a custom function upper
is defined to convert a string to uppercase.
Conclusion
Go’s text/template
package provides a powerful way to generate dynamic text by combining static content with data. By understanding how to define templates, pass data to templates, use control structures, and extend templates with custom functions, you can create flexible and efficient text generation systems in your Go applications.