Created
March 31, 2025 17:40
-
-
Save rorycl/ee841bbee0f1bf9389c7af8481cd1cce to your computer and use it in GitHub Desktop.
Cache golang parsed templates to avoid reparsing unless in development mode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
// Assumes a directory next to this file called "templates" | |
// containing "home.html", "forest.html" | |
import ( | |
"embed" | |
"fmt" | |
"html/template" | |
"io" | |
"io/fs" | |
"os" | |
) | |
//go:embed templates | |
var templates embed.FS | |
type cachedTemplate struct { | |
fs fs.FS | |
templates map[string]*template.Template | |
inDevelopment bool | |
} | |
func NewCachedTemplate(dir string, inDevelopment bool) (*cachedTemplate, error) { | |
_, err := os.Stat(dir) | |
if err != nil { | |
return nil, err | |
} | |
c := cachedTemplate{ | |
inDevelopment: inDevelopment, | |
templates: map[string]*template.Template{}, | |
} | |
if inDevelopment { | |
c.fs = os.DirFS(dir) | |
} else { | |
c.fs, err = fs.Sub(templates, dir) | |
if err != nil { | |
return nil, err | |
} | |
} | |
return &c, nil | |
} | |
func (c *cachedTemplate) ParseFS(name string, pages ...string) error { | |
var err error | |
if !c.inDevelopment { | |
if _, ok := c.templates[name]; ok { | |
// cache hit | |
return nil | |
} | |
} | |
c.templates[name], err = template.ParseFS(c.fs, pages...) | |
return err | |
} | |
func (c *cachedTemplate) Execute(name string, w io.Writer, data any) error { | |
tpl, ok := c.templates[name] | |
if !ok { | |
return fmt.Errorf("template %s not yet parsed", name) | |
} | |
return tpl.Execute(w, data) | |
} | |
func main() { | |
earlyExit := func(err error) { | |
if err != nil { | |
fmt.Println(err) | |
os.Exit(1) | |
} | |
} | |
c, err := NewCachedTemplate("templates", false) | |
earlyExit(err) | |
err = c.ParseFS("home", "home.html", "forest.html") | |
earlyExit(err) | |
err = c.Execute("home", os.Stdout, map[string]string{"Name": "Totoro"}) | |
earlyExit(err) | |
// cachehit? | |
err = c.ParseFS("home", "home.html", "forest.html") | |
earlyExit(err) | |
err = c.Execute("home", os.Stdout, map[string]string{"Name": "Totoro"}) | |
earlyExit(err) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment