一种不同的方法,一个有才华的开发我想出了工作是进行后处理的模板实例找到任何模板包括没有被定义并期待匹配文件的文件系统并为每个找到的文件系统解析它;然后渲染。
这给你一个设置类似如下:
的意见/ 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