一種不同的方法,一個有才華的開發我想出了工作是進行後處理的模板實例找到任何模板包括沒有被定義並期待匹配文件的文件系統併爲每個找到的文件系統解析它;然後渲染。
這給你一個設置類似如下:
的意見/ index.html的:
{{template "/includes/page-wrapper.html" .}}
{{define "body"}}
<div>Page guts go here</div>
{{end}}
{{define "head_section"}}
<title>Title Tag</title>
{{end}}
包括/頁wrapper.html:
<html>
<head>
{{block "head_section" .}}{{end}}
<head>
<body>
{{template "body" .}}
</body>
</html>
而且你ServeHTTP()
方法查找「views」目錄中的文件,加載並解析它,然後調用TmplIncludeAll()
(如下)。
我最終將這個基本概念作爲幾個函數進行了調整,如下所示。 t
是分析之後但呈現之前的模板。而fs
是「視圖」和「包含」直播的目錄(參見上文)。
func TmplIncludeAll(fs http.FileSystem, t *template.Template) error {
tlist := t.Templates()
for _, et := range tlist {
if et != nil && et.Tree != nil && et.Tree.Root != nil {
err := TmplIncludeNode(fs, et, et.Tree.Root)
if err != nil {
return err
}
}
}
return nil
}
func TmplIncludeNode(fs http.FileSystem, t *template.Template, node parse.Node) error {
if node == nil {
return nil
}
switch node := node.(type) {
case *parse.TemplateNode:
if node == nil {
return nil
}
// if template is already defined, do nothing
tlist := t.Templates()
for _, et := range tlist {
if node.Name == et.Name() {
return nil
}
}
t2 := t.New(node.Name)
f, err := fs.Open(node.Name)
if err != nil {
return err
}
defer f.Close()
b, err := ioutil.ReadAll(f)
if err != nil {
return err
}
_, err = t2.Parse(string(b))
if err != nil {
return err
}
// start over again, will stop recursing when there are no more templates to include
return TmplIncludeAll(fs, t)
case *parse.ListNode:
if node == nil {
return nil
}
for _, node := range node.Nodes {
err := TmplIncludeNode(fs, t, node)
if err != nil {
return err
}
}
case *parse.IfNode:
if err := TmplIncludeNode(fs, t, node.BranchNode.List); err != nil {
return err
}
if err := TmplIncludeNode(fs, t, node.BranchNode.ElseList); err != nil {
return err
}
case *parse.RangeNode:
if err := TmplIncludeNode(fs, t, node.BranchNode.List); err != nil {
return err
}
if err := TmplIncludeNode(fs, t, node.BranchNode.ElseList); err != nil {
return err
}
case *parse.WithNode:
if err := TmplIncludeNode(fs, t, node.BranchNode.List); err != nil {
return err
}
if err := TmplIncludeNode(fs, t, node.BranchNode.ElseList); err != nil {
return err
}
}
return nil
}
這是我最喜歡的方法,我已經使用了一段時間了。它的優點是隻有一個模板渲染,錯誤信息很好,乾淨,Go模板標記非常易讀和明顯。如果HTML /模板的膽量會很大。模板使這個實現起來更簡單,但它總體上是一個很好的解決方案IMO。
@Boushley gotcha。看到我剛剛發佈的其他答案,它提供了我最終使用的解決方案。 –
在此期間得到了答案? – Kiril
我也在尋找一種辦法... – Creasixtine