Text and HTML templates

suggest change

Imagine you’re working on a web application and need to return HTML that lists most recent tweets. You need to load list of tweets from a database and create HTML based on that information.

Building that HTML string by building smaller strings and concatenating them with + would be tedious.

Packages text/template and html/template in Go standard library make implement data-driven templates for generating textual output:

tempates.go

var tmplStr = `User {{.User}} has {{.TotalTweets}} tweets.
{{- $tweetCount := len .RecentTweets }}
Recent tweets:
{{range $idx, $tweet := .RecentTweets}}Tweet {{$idx}} of {{$tweetCount}}: '{{.}}'
{{end -}}
Most recent tweet: '{{index .RecentTweets 0}}'
`

	t := template.New("tweets")
	t, err := t.Parse(tmplStr)
	if err != nil {
		log.Fatalf("template.Parse() failed with '%s'\n", err)
	}
	data := struct {
		User         string
		TotalTweets  int
		RecentTweets []string
	}{
		User:         "kjk",
		TotalTweets:  124,
		RecentTweets: []string{"hello", "there"},
	}
	err = t.Execute(os.Stdout, data)
	if err != nil {
		log.Fatalf("t.Execute() failed with '%s'\n", err)
	}

Output:

User kjk has 124 tweets.
Recent tweets:
Tweet 0 of 2: 'hello'
Tweet 1 of 2: 'there'
Most recent tweet: 'hello'

Each template has a name. template.New("tweets") creates an empty template with name tweets.

t.Parse(s string) parses the template.

t.Execute(w io.Writer, v interface{}) executes the template with a given value and writing the result to an io.Writer.

{{ ... }} is an action are instructions for templating engine.

{{.TweetCount}} means printing the value of TweetCount in current context.

Data passed to a template can be hierarchical (i.e. a struct withing a struct within a struct…).

Current context . refers to current scope within the data.

Initial . refers to top-level scope:

tempaltes.go

	tmplStr := "Data: {{.}}\n"
	t := template.Must(template.New("simple").Parse(tmplStr))
	execWithData := func(data interface{}) {
		err := t.Execute(os.Stdout, data)
		if err != nil {
			log.Fatalf("t.Execute() failed with '%s'\n", err)
		}
	}

	execWithData(5)
	execWithData("foo")
	st := struct {
		Number int
		Str    string
	}{
		Number: 3,
		Str:    "hello",
	}
	execWithData(st)

Output:

Data: 5
Data: foo
Data: {3 hello}

Values that don’t have pre-defined formatting are printed using Stringer interface. For custom formatting of your type in a template implement String() string method.

{{range .Tweets}}{{end}} evaluates inner part for every element of []string slice Tweets and sets current context . within the inner part to elements of Tweets slice.

{{index .RecentTweets 0}} is equivalent to RecentTweets[0] in Go code.

Text in a template is copied verbatim. Having to preserve whitespace can lead to ugly templates.

To help write more readable templates We can add - at the beginning or end of action as seen in {{end -}}.

This remove whitespace before or after the action.

{{range .RecentTweets}} changes variable scope and we don’t have access to data outside. If we need to access data from upper scope, we can define variables like {{ $tweetCount := len .RecentTweets }}.

Methods as data

if action

range action

Built-in functions

Custom functions

HTML templates

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents