Как указать несколько путей для компиляции шаблонов?
В руководстве приведен пример:
t := &Template{
templates: template.Must(template.ParseGlob("public/views/*.html")),
}
в котором компилируются шаблоны по пути public/views/*.html.
Мне необходимо этот код изменить так, чтобы компилировались шаблоны не по одному, а по двум указанным путям, а именно pjt_*/templates/include/*.html и pjt_*/templates/site/*.html.
Мой код:
package main
import (
"html/template"
"io"
"net/http"
"github.com/labstack/echo/v4"
)
type TemplateRenderer struct {
templates *template.Template
}
func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
if viewContext, isMap := data.(map[string]interface{}); isMap {
viewContext["reverse"] = c.Echo().Reverse
}
return t.templates.ExecuteTemplate(w, name, data)
}
func main() {
e := echo.New()
e.Renderer = &TemplateRenderer{
// тут хочу, чтобы компилировались шаблоны, не только по
// "pjt_*/templates/include/*.html", но и по "pjt_*/templates/site/*.html"
templates: template.Must(template.ParseGlob("pjt_*/templates/include/*.html")),
}
e.GET("/something", func(c echo.Context) error {
return c.Render(http.StatusOK, "template.html", "World")
})
e.Logger.Fatal(e.Start(":8000"))
}
ПС руководство, на всякий: https://echo.labstack.com/guide/templates/
Ответы (1 шт):
Не ограничивайте себя только примерами из руководств, читайте документацию. Тогда вы точно найдёте для себя больше возможностей.
Например, обратите внимание на функцию template.ParseFiles - она создаёт шаблон из списка файлов.
Как получить список файлов по маске? Для этого есть функция filepath.Glob
Как объединить списки файлов, соответствующих разным маскам? Для этого подойдёт банальный встроенный append. Итого может получиться что-то вроде такого:
package main
import (
"html/template"
"path/filepath"
"fmt"
)
const (
INCLUDE_GLOB = `./pjt_*/templates/include/*.html`
SITE_GLOB = `./pjt_*/templates/site/*.html`
)
func main() {
files := []string{}
includes, err := filepath.Glob(INCLUDE_GLOB)
if err != nil { panic(err) }
files = append(files, includes...)
sites, err := filepath.Glob(SITE_GLOB)
if err != nil { panic(err) }
files = append(files, sites...)
fmt.Printf("Files: %v\n", files)
t, err := template.ParseFiles(files...)
if err != nil { panic(err) }
println(t)
}
Я для примера положил в каждый каталог файлы с именами a.html и b.html. Получилось вот что:
Files: [pjt_1/templates/include/a.html pjt_1/templates/include/b.html pjt_2/templates/include/a.html pjt_2/templates/include/b.html pjt_1/templates/site/a.html pjt_1/templates/site/b.html pjt_2/templates/site/a.html pjt_2/templates/site/b.html]
Вроде как раз то, что вам нужно. Всего за пять минут чтения документации.
UPDATE
Как это использовать. template.ParseFile собирает коллекцию шаблонов. Ключом в этой коллекции служит имя файла - то, которое после последнего слеша. Поэтому если у вас есть несколько файлов с именем template.html в разных каталогах, то ParseFile запомнит последний встреченный файл template.html.
Ниже пример, который работает на моей машине. У меня структура файлов такая:
├── pjt_1
│ └── templates
│ ├── include
│ │ ├── a.html
│ │ └── b.html
│ └── site
│ ├── a.html
│ └── b.html
└── pjt_2
└── templates
├── include
│ ├── a.html
│ └── b.html
└── site
├── a.html
└── b.html
В примере ниже эти файлы парсятся и собираются в шаблон. Я хочу вывести для запроса /something содержимое шаблона a.html - так и пишу:
e.GET("/something", func(c echo.Context) error {
return c.Render(http.StatusOK, "a.html", "World")
})
В результате выводится содержимое файла pjt_2/templates/site/a.html
package main
import (
"fmt"
"html/template"
"io"
"net/http"
"path/filepath"
"github.com/labstack/echo/v4"
)
type TemplateRenderer struct {
templates *template.Template
}
func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
if viewContext, isMap := data.(map[string]interface{}); isMap {
viewContext["reverse"] = c.Echo().Reverse
}
return t.templates.ExecuteTemplate(w, name, data)
}
const (
INCLUDE_GLOB = `./pjt_*/templates/include/*.html`
SITE_GLOB = `pjt_*/templates/site/*.html`
)
func main() {
files := []string{}
includes, err := filepath.Glob(INCLUDE_GLOB)
if err != nil {
panic(err)
}
files = append(files, includes...)
sites, err := filepath.Glob(SITE_GLOB)
if err != nil {
panic(err)
}
files = append(files, sites...)
fmt.Printf("Files: %v\n", files)
e := echo.New()
e.Renderer = &TemplateRenderer{
templates: template.Must(template.ParseFiles(files...)),
}
e.GET("/something", func(c echo.Context) error {
return c.Render(http.StatusOK, "a.html", "World")
})
e.Logger.Fatal(e.Start(":8000"))
}