Да, это возможно. html.Template
Фактически A - это набор файлов шаблонов. Если вы выполняете определенный блок в этом наборе, он имеет доступ ко всем другим блокам, определенным в этом наборе.
Если вы создадите карту таких наборов шаблонов самостоятельно, вы получите в основном такую же гибкость, которую предлагает Jinja / Django. Единственное отличие состоит в том, что пакет html / template не имеет прямого доступа к файловой системе, поэтому вам придется анализировать и составлять шаблоны самостоятельно.
Рассмотрим следующий пример с двумя разными страницами («index.html» и «other.html»), которые наследуются от «base.html»:
{{define "base"}}<html>
<head>{{template "head" .}}</head>
<body>{{template "body" .}}</body>
</html>{{end}}
{{define "head"}}<title>index</title>{{end}}
{{define "body"}}index{{end}}
{{define "head"}}<title>other</title>{{end}}
{{define "body"}}other{{end}}
И следующая карта наборов шаблонов:
tmpl := make(map[string]*template.Template)
tmpl["index.html"] = template.Must(template.ParseFiles("index.html", "base.html"))
tmpl["other.html"] = template.Must(template.ParseFiles("other.html", "base.html"))
Теперь вы можете отобразить свою страницу index.html, вызвав
tmpl["index.html"].Execute("base", data)
и вы можете отобразить свою страницу "other.html", позвонив
tmpl["other.html"].Execute("base", data)
С помощью некоторых уловок (например, согласованного соглашения об именах файлов шаблонов) можно даже tmpl
автоматически сгенерировать карту.
tmpl["index.html"].ExecuteTemplate(w, "base", data)
.{{ .SomeData }}
не будут отображаться во внутреннем шаблоне. Наружные работы.template.ParseFiles("index.html", "base.html")
естьtemplate.ParseFiles("base.html", "index.html")
?обратите внимание, когда вы выполняете свой базовый шаблон, вы должны передавать значения дочерним шаблонам, здесь я просто передаю ".", чтобы все было передано вниз.
первый шаблон отображает {{.}}
{{define "base"}} <html> <div class="container"> {{.}} {{template "content" .}} </div> </body> </html> {{end}}
во втором шаблоне отображается {{.domains}}, переданный в родительский.
{{define "content"}} {{.domains}} {{end}}
Обратите внимание: если бы мы использовали {{template "content".}} Вместо {{template "content".}}, Домены не были бы доступны из шаблона содержимого.
DomainsData := make(map[string]interface{}) DomainsData["domains"] = domains.Domains if err := groupsTemplate.ExecuteTemplate(w, "base", DomainsData); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) }
источник
поработав с другими пакетами шаблонов, теперь, когда я в основном работаю со стандартным пакетом html / template, думаю, я был наивен, чтобы не оценить простоту, которую он предоставляет, и другие полезности. Я использую очень похожий подход к принятому ответу со следующими изменениями
вам не нужно оборачивать свои макеты дополнительным
base
шаблоном, блок шаблона создается для каждого проанализированного файла, поэтому в этом случае он избыточен, мне также нравится использовать действие блока, предусмотренное в новой версии go, что позволяет вам иметь содержимое блока по умолчанию, если вы не предоставляете его в дочерних шаблонах// base.html <head>{{block "head" .}} Default Title {{end}}</head> <body>{{block "body" .}} default body {{end}}</body>
и ваши шаблоны страниц могут быть такими же, как
// Content of index.html: {{define "head"}}<title>index</title>{{end}} {{define "body"}}index{{end}} // Content of other.html: {{define "head"}}<title>other</title>{{end}} {{define "body"}}other{{end}}
теперь для выполнения шаблонов вам нужно называть это так
tmpl["index.html"].ExecuteTemplate(os.Stdout, "base.html", data)
источник
Используйте Pongo , который представляет собой супернабор шаблонов Go, который поддерживает теги {{extends}} и {{block}} для наследования шаблонов, как и Django.
источник
Я возвращался к этому ответу в течение нескольких дней, наконец, укусил пулю и написал для этого небольшой слой абстракции / предварительный процессор. Это в основном:
https://github.com/daemonl/go_sweetpl
источник