package main import ( "html/template" "log" "os" "path/filepath" "time" "github.com/gin-gonic/gin" ) var tm *TemplateManager func init() { tm = NewTemplateManager("templates", "base", "html") } type TemplateManager struct { templates map[string]*template.Template funcs template.FuncMap base string ext string dir string } // NewTemplateManager initializes the manager and loads templates func NewTemplateManager(dir string, base string, ext string) *TemplateManager { tm := &TemplateManager{ templates: make(map[string]*template.Template), funcs: template.FuncMap{ // Attach functions to the templates here "fmtTime": func(t time.Time) string { return t.Local().Format("2006-01-02 15:04") // Go’s reference time }, "cmpTwo": func(a, b int) bool { return a == b }, }, base: base, dir: dir, ext: ext, } // Populate template manager tm.LoadTemplates() return tm } // LoadTemplates parses the base template with each view template in the directory func (tm *TemplateManager) LoadTemplates() { pattern := filepath.Join(tm.dir, "*."+tm.ext) files, err := filepath.Glob(pattern) if err != nil { panic(err) } base := filepath.Join(tm.dir, tm.base+"."+tm.ext) for _, file := range files { if filepath.Base(file) == tm.base { continue } name := stripAfterDot(filepath.Base(file)) // Parse base + view template together tpl, err := template.New(name). Funcs(tm.funcs). ParseFiles(base, file) if err != nil { panic(err) } tm.templates[name] = tpl } } // Render executes a template by name into the given context func (tm *TemplateManager) Render(c *gin.Context, name string, data gin.H) error { u := getSessionUser(c) // Prefil the data for the render data["CurrentUser"] = u // Try to get information from current context that is filled from the session middleware data["Form"], _ = c.Get("form") data["Message"], _ = c.Get("mes") tpl, ok := tm.templates[name] if !ok { return os.ErrNotExist } if err := tpl.ExecuteTemplate(c.Writer, tm.base, data); err != nil { log.Println("template error:", err) c.Status(500) return err } return nil }