liveBook · Manning

Template inheritance

As explained in Go in Practice, Second Edition

Template inheritance is a composition pattern in which an extending template fills or overrides sections defined by a shared base template.

Use template inheritance when several HTML pages need the same layout but different content. A shared base defines the page structure; each extending template supplies named sections. Unlike including a shared subtemplate in several top-level pages, this pattern shares the top-level template itself. section 9.1.5

In Go’s html/template, treat sections—not files—as templates. Define the shared layout with {{define "base"}}. Call {{template "title" .}} and {{template "content" .}} where page-specific content is required. Use {{block "styles" .}}…{{end}} or an empty scripts block for sections with defaults; an extending template can redefine them. The dot passes the current data into each section. section 9.1.5

A page that extends a base

A user page can define title as “User: {{.Username}}” and content as a list of user details. A different page can define title and content from its own data and also redefine styles to change the heading color. Parse base.html with each page file into a separate template set, then execute the named base template with that page’s data. Keeping the sets separate lets each page provide its own definitions. section 9.1.5

Listing 9.11 A base template to inherit from
{{define "base"}}<!DOCTYPE HTML>   #1
<html>
  <head>
    <meta charset="utf-8">
    <title>{{template "title" .}}</title>    #2
    {{ block "styles" . }}<style>   #3
      h1 {                          #3
        color: #400080              #3
      }                             #3
    </style>{{ end }}               #3
  </head> #3
  <body>
     <h1>{{template "title" .}}</h1>
     {{template "content" .}}
     {{block "scripts" .}}{{end}}    #4
  </body>
</html>{{end}}   #5

Inspect the base layout to see required title and content calls beside default styles and scripts blocks. section 9.1.5

Listing 9.14 Using template inheritance
package main

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

var t map[string]*template.Template     #1
func init() {
     t = make(map[string]*template.Template)             #2
     temp := template.Must(template.ParseFiles(
     "base.html", "user.html"))                                   #3
     t["user.html"] = temp                                
     temp = template.Must(template.ParseFiles(
     "base.html", "page.html"))                                   
     t["page.html"] = temp                                
}

type Page struct {            #4
     Title, Content string    #4
}                             #4

type User struct {            #4
     Username, Name string    #4
}                             #4

func displayPage(w http.ResponseWriter, r *http.Request) {
     p := &Page{                                            #5
            Title:   "An Example",                          #5
            Content: "Have fun stormin' da castle.",        #5
     }                                                      #5
     t["page.html"].ExecuteTemplate(w, "base", p)        #6
}

func displayUser(w http.ResponseWriter, r *http.Request) {
     u := &User{
            Username: "swordsmith",
            Name:     "Inigo Montoya",
     }
     t["user.html"].ExecuteTemplate(w, "base", u)
}

func main() {
     http.HandleFunc("/user", displayUser)   #7
     http.HandleFunc("/", displayPage)       #7
     http.ListenAndServe(":8080", nil)       #7
}

Inspect the Go setup that pairs the base with each extending file for HTTP rendering. section 9.1.5

This is an inheritance pattern, not the full range of inheritance offered by some template systems. It works by combining named templates into a usable set for each page. section 9.1.5

How Go in Practice, Second Edition covers it

How deep it goes
Works through base and extending templates, directives, and Go setup; stops short of claiming full template-system inheritance.
Examples
Demonstrates a user page and a general page, including an optional styles override.
What it assumes
Assumes basic Go template and HTTP concepts while introducing define and block directives for composing pages.
What you can do after
Build it from scratch with html/template by pairing a base with page-specific definitions and executing the named template.
How it connects
Connects named subtemplates, block directives, template parsing, and HTTP rendering.

Also explained in

Compare how 3 books explain template inheritance →

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.