Golang:解析目录和子目录中的所有模板?

Sun*_*nny 5 go

这是我的目录结构:

app/
  template/
    layout/
      base.tmpl
    index.tmpl
Run Code Online (Sandbox Code Playgroud)

template.ParseGlob("*/*.tmpl")解析index.tmpl而不是base.tmpllayout子目录中.有没有办法递归地解析所有模板?

Dat*_*sik 12

不是没有实现自己的功能,我一直在使用这样的东西

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
}
Run Code Online (Sandbox Code Playgroud)

这将解析您的所有模板,然后您可以通过调用它们的名称来渲染它们,例如

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

  • 这样的耻辱不在标准库中.但是好事并不难实现. (3认同)
  • 如果多个目录包含具有相同名称的文件,这不会很好地工作。使用 ParseFiles,模板的名称是从文件路径的基本名称中获得的;这可能会导致名称冲突。 (2认同)

小智 8

如果它不是深度嵌套(如果您事先知道子目录的名称),您可以这样做:

t := template.Must(template.ParseGlob("template/*.tmpl"))
template.Must(t.ParseGlob("template/layout/*.tmpl"))
Run Code Online (Sandbox Code Playgroud)

然后对每个子目录执行与“布局”相同的操作


Ric*_*777 6

Datsik的答案的缺点是,当多个目录包含许多模板时,就会出现名称冲突的问题。如果不同目录中的两个模板具有相同的文件名,则无法正常工作:仅其中两个模板可用。

这是由template.ParseFiles的实现引起的,因此我们可以通过避免template.ParseFiles来解决它。这是一个修改后的步行算法,可以执行此操作;它直接使用template.Parse。

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)
            t, e2 = t.Parse(string(b))
            if e2 != nil {
                return e2
            }
        }

        return nil
    })

    return root, err
}
Run Code Online (Sandbox Code Playgroud)

这将解析所有模板,然后您可以通过调用它们的名称来渲染它们,例如

template.ExecuteTemplate(w, "a/home.html", nil)
Run Code Online (Sandbox Code Playgroud)