Golang多模板缓存

I'm new to the world of Golang and I'm trying to set up a web project with templates files and good caching system.

I have layout.html, 1.html, 2.html.

So I load layout.html in my render function :

err := templates.ExecuteTemplate(w, "layout.html", nil)

layout.html look like this :

...   
<body>{{template "content" .}}</body>
...

1.html

{{define "content"}}This is the first page.{{end}}

2.html

{{define "content"}}This is the second page.{{end}}

I can't use

var templates = template.Must(template.ParseFiles(
    "layout.html",
    "1.html",
    "2.html"))

Because 2.html override 1.html.

So I have two ways :

  1. Define ParseFiles in each handler function. (every time a page is rendered) Very bad perf
  2. Define an array of template like this in the init function (example): templates["1"] = template.Must(template.ParseFiles("layout.html","1.html")) templates["2"] = template.Must(template.ParseFiles("layout.html","2.html"))

Is there any new way or better way to do this ?

Package-level maps or variables are both a good way to cache compiled templates. Code in #2 above is OK. Here's how to use package-level variables:

var t1 = template.Must(template.ParseFiles("layout.html","1.html"))
var t2 = template.Must(template.ParseFiles("layout.html","2.html"))

Use the variables like this:

err := t1.Execute(w, data)

The code in the question and this code above in this answer load "layout.html" twice. This can be avoided:

var layout = template.Must(template.ParseFiles("layout.html"))
var t1 = template.Must(layout.Clone().ParseFiles("1.html"))
var t2 = template.Must(layout.Clone().ParseFiles("2.html"))

In my projects I use this helper function:

func executeTemplate(tmpls *template.Template, tmplName string, w io.Writer, data interface{}) error {
    var err error
    layout := tmpls.Lookup("layout.html")
    if layout == nil {
        return errNoLayout
    }

    layout, err = layout.Clone()
    if err != nil {
        return err
    }

    t := tmpls.Lookup(tmplName)
    if t == nil {
        return errNoTemplate
    }

    _, err = layout.AddParseTree("content", t.Tree)
    if err != nil {
        return err
    }

    return layout.Execute(w, data)
}

tmpls is the template which contains all parsed templates as "sub-templates", e.g. from ParseFiles. layout.html looks something like this:

<main class="container">
{{template "content" .}}
</main>

While other templates are like this:

<h1>Welcome</h1>

Notice, content templates don't need to start with {{define "content"}}.