Q:

Golang: Parse all templates in directory and subdirectories?

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?

A:

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)

A:

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)

A:

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'

