liveBook · Manning

Template.HTML

As explained in Go in Practice, Second Edition

template.HTML is a Go html/template type representing trusted HTML content that is intended to bypass normal contextual escaping.

Go’s html/template escapes ordinary string values according to where they appear in a page. This lets a template display user-supplied text without treating an embedded <script> tag as markup. template.HTML takes a different path: it marks a value as HTML that should be rendered without normal escaping. Use it only when you are responsible for the content being safe to display unescaped. section 9.1.1

A practical use is assembling a page from separately rendered pieces. Render an object with its own template, capture the resulting HTML, then pass it to a page wrapper as template.HTML. The wrapper can insert the fragment without knowing the object’s data type or rendering rules. A reusable rendered fragment can also avoid repeated data lookups and rendering when a page is generated. section 9.1.5

Insert a rendered quote into a page

A quote template supplies the <blockquote> markup and inserts quote fields through template actions. Its rendered output becomes the Content field of a generic page wrapper; declaring that field as template.HTML keeps the blockquote from being escaped when the wrapper renders it. The distinction matters: template.HTML is appropriate for the rendered fragment, not for arbitrary input that happens to contain HTML. section 9.1.5 section 9.1.1

Listing 9.17 Bringing the templates together
package main

import (
     "bytes"
     "html/template"
     "net/http"
)

var t *template.Template   #1
var qc template.HTML       #1
func init() {
     t = template.Must(template.ParseFiles("index.html
     ", "quote.html"))            #2
}

type Page struct {            #3
     Title   string           #3
     Content template.HTML    #3
}                             #3

type Quote struct {           #3
     Quote, Name string       #3
}                             #3

func main() {
     q := &Quote{                                        #4
            Quote: `You keep using that word. I do not   #4
            think it means what you think it means.`,    #4
            Person: "Inigo Montoya",                     #4
     } #4
     var b bytes.Buffer                     #5
     t.ExecuteTemplate(&b, "quote.html", q)
     qc = template.HTML(b.String())           #6
     http.HandleFunc("/", displayPage)        #7
     http.ListenAndServe(":8080", nil)        #7
}
func displayPage(w http.ResponseWriter, r *http.Request) {
     p := &Page{                  #8
            Title:   "A User",    #8
            Content: qc,          #8
     }                            #8
     t.ExecuteTemplate(w, "index.html", p)   #9
}

The Go listing shows the assembly point: a bytes.Buffer receives the object template’s output, and the page’s Content field is typed template.HTML for insertion into the higher-level template. section 9.1.5

How Go in Practice, Second Edition covers it

How deep it goes
Explains the escaping trade-off and walks through a buffered, two-stage rendering pattern; does not detail escaping internals.
Examples
Shows a quote template rendered into a buffer and inserted as Content in a generic HTML page wrapper.
What it assumes
Assumes familiarity with Go templates and template execution; clarifies why ordinary strings are escaped and trusted HTML is not.
What you can do after
Apply it via Go’s html/template to insert a separately rendered HTML fragment while retaining responsibility for its safety.
How it connects
Connects html/template contextual escaping, cross-site scripting, template composition, and caching rendered fragments.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go in Practice, Second Edition. The section links point to the parts of the book it draws on.