Как загрузить шаблоны в подкаталогах - PullRequest
0 голосов
/ 28 марта 2020

В настоящее время все мои html файлы находятся в плоском каталоге templates/, и я загружаю все с помощью

tmpl := template.Must(template.ParseGlob("templates/*.html"))

Но я бы хотел теперь внести некоторую структуру и поместить шаблоны в папки components, base и др. c. Но когда я делаю, мой сайт перестает работать. Я думаю, что это может быть выше, или это может быть связано с указанием пути в шаблоне?

пример

{{ template "navbar" }}

станет

{{ template "components/navbar" }}

Немного смущен ...

Я также сейчас использую нативную библиотеку go, а не фреймворк.

1 Ответ

3 голосов
/ 28 марта 2020

Go glob не поддерживает сопоставление файлов в подкаталогах, т. Е. ** не поддерживается.

Вы можете использовать стороннюю библиотеку lib (существует множество реализаций на github ), или вы можете вызвать filepath.Glob для каждого «уровня» подкаталогов и объединить имена возвращенных файлов в один фрагмент, а затем передать фрагмент в template.ParseFiles:

dirs := []string{
    "templates/*.html",
    "templates/*/*.html",
    "templates/*/*/*.html",
    // ...
}

files := []string{}
for _, dir := range dirs {
    ff, err := filepath.Glob(dir)
    if err != nil {
        panic(err)
    }
    files = append(files, ff...)
}

t, err := template.ParseFiles(files...)
if err != nil {
    panic(err)
}

// ...

Вам также необходимо помнить, как работает ParseFiles: (выделено)

ParseFiles создает новый шаблон и анализирует определения шаблона из именованные файлы. Имя возвращаемого шаблона будет иметь (базовое) имя и (проанализированное) содержимое первого файла. Там должен быть хотя бы один файл. Если возникает ошибка, синтаксический анализ прекращается, и возвращаемый шаблон * равен nil.

При синтаксическом анализе нескольких файлов с одинаковыми именами в разных каталогах будет получен последний упомянутый файл. Например, ParseFiles ("a / foo", "b / foo") сохраняет "b / foo" в качестве шаблона с именем "foo", в то время как "a / foo" недоступен.

This означает, что, если вы хотите загрузить все файлы, вы должны убедиться по крайней мере в одной из двух вещей: (1) что имя base каждого файла уникально для всех файлов шаблона, а не только в каталоге в в котором находится файл, или (2) укажите уникальное имя шаблона для каждого файла, используя действие {{ define "<template_name>" }} в верхней части содержимого файла (и не забудьте {{ end }}, чтобы закрыть действие define).


В качестве примера для второго подхода, скажем, в ваших шаблонах у вас есть два файла с одинаковым базовым именем, например templates/foo/header.html и templates/bar/header.html, и их содержимое выглядит следующим образом:

templates/foo/header.html

<head><title>Foo Site</title></head>

templates/bar/header.html

<head><title>Bar Site</title></head>

Теперь, чтобы дать этим файлам уникальное имя шаблона, вы можете изменить его содержимое на следующее:

templates/foo/header.html

{{ define "foo/header" }}
<head><title>Foo Site</title></head>
{{ end }}

templates/bar/header.html

{{ define "bar/header" }}
<head><title>Bar Site</title></head>
{{ end }}

После того, как вы это сделаете, вы можете выполнить их напрямую с помощью t.ExecuteTemplate(w, "foo/header", nil) или косвенно, если другие шаблоны ссылаются на них с помощью действия {{ template "bar/header" . }}.

...