Golang: Parse all templates in directory and subdirectories?

血红的双手。 提交于 2021-01-19 22:54:24

问题


This is my directory structure:

app/
  template/
    layout/
      base.tmpl
    index.tmpl

template.ParseGlob("*/*.tmpl") parses index.tmpl but not base.tmpl in the layout subdirectory. Is there a way to parse all templates recursively?


回答1:


Not without implementing your own function to do it, I've been using something like this

func ParseTemplates() *template.Template {
    templ := template.New("")
    err := filepath.Walk("./views", func(path string, info os.FileInfo, err error) error {
        if strings.Contains(path, ".html") {
            _, err = templ.ParseFiles(path)
            if err != nil {
                log.Println(err)
            }
        }

        return err
    })

    if err != nil {
        panic(err)
    }

    return templ
}

This will parse all your templates then you can render them by calling their names e.g.

template.ExecuteTemplate(w, "home", nil)




回答2:


Datsik's answer has the drawback that there are name collision issues when several directories contain many templates. If two templates in different directories have the same filename it won't work properly: only the second of them will be usable.

This is caused by the implementation of template.ParseFiles, so we can solve it by avoiding template.ParseFiles. Here's a modified walk algorithm that does this by using template.Parse directly instead.

func findAndParseTemplates(rootDir string, funcMap template.FuncMap) (*template.Template, error) {
    cleanRoot := filepath.Clean(rootDir)
    pfx := len(cleanRoot)+1
    root := template.New("")

    err := filepath.Walk(cleanRoot, func(path string, info os.FileInfo, e1 error) error {
        if !info.IsDir() && strings.HasSuffix(path, ".html") {
            if e1 != nil {
                return e1
            }

            b, e2 := ioutil.ReadFile(path)
            if e2 != nil {
                return e2
            }

            name := path[pfx:]
            t := root.New(name).Funcs(funcMap)
            _, e2 = t.Parse(string(b))
            if e2 != nil {
                return e2
            }
        }

        return nil
    })

    return root, err
}

This will parse all your templates then you can render them by calling their names e.g.

template.ExecuteTemplate(w, "a/home.html", nil)



回答3:


if it is not deeply nested (if you know names of sub-directories beforehand) you can just do this:

t := template.Must(template.ParseGlob("template/*.tmpl"))
template.Must(t.ParseGlob("template/layout/*.tmpl"))

Then for each sub-directory do the same as for 'layout'




回答4:


You can load multiple subdirectories this way. Here we ignore if subdirectories do not exist. But we want to make sure that the first directory can be loaded.

func ParseTemplates() (*template.Template, error) {
    templateBuilder := template.New("")
    if t, _ := templateBuilder.ParseGlob("/*/*/*/*/*.tmpl"); t != nil {
        templateBuilder = t
    }
    if t, _ := templateBuilder.ParseGlob("/*/*/*/*.tmpl"); t != nil {
        templateBuilder = t
    }
    if t, _ := templateBuilder.ParseGlob("/*/*/*.tmpl"); t != nil {
        templateBuilder = t
    }
    if t, _ := templateBuilder.ParseGlob("/*/*.tmpl"); t != nil {
        templateBuilder = t
    }
    return templateBuilder.ParseGlob("/*.tmpl")
}



回答5:


I made a package that solves exactly this problem.

https://github.com/karelbilek/template-parse-recursive

package main

import (
    "html/template"
    "os"

    recurparse "github.com/karelbilek/template-parse-recursive"
)

func main() {
    t, err := recurparse.HTMLParse(
        template.New("templates"), 
        "path/to/templates", 
        "*.html",
    )
   
    if err != nil {
        panic(err)
    }
    
    templateUnder := t.Lookup("subdir/subdir/template.html")
    templateUnder.Execute(os.Stdout, nil)
}


来源:https://stackoverflow.com/questions/38686583/golang-parse-all-templates-in-directory-and-subdirectories

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!