我看不到使用动态名称调用模板(文本或HTML)的方法.示例:

这是可行的:

{{template "Blah" .}}

此错误为"意外"$BlahVar"在模板调用中":

{{$BlahVar := "Blah"}}
{{template $BlahVar .}}

我试图解决的总体问题是,我需要基于配置文件有条件地呈现模板-所以我不知道模板的名称.显然,我可以在FuncMap中放置一个函数,它只执行单独的模板解析和调用,并返回结果,但是我想知道是否有更好的方法.

推荐答案

与我一起工作的一位才华横溢的开发人员设想的另一种方法是对模板实例进行后处理,以找到任何未定义的模板,并在文件系统中查找匹配的文件并对找到的每个文件进行解析;然后呈现.

这将为您提供如下设置:

Views/index.html:

{{template "/includes/page-wrapper.html" .}}

{{define "body"}}
<div>Page guts go here</div>
{{end}}

{{define "head_section"}}
<title>Title Tag</title>
{{end}}

包括/页面包装器.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/template.template的毅力可以简化实现,那就太好了,但总的来说,它是一个很好的解决方案.

Go相关问答推荐

Golang socks 5代理,流量限制转发到下一个socks 5代理

在字符串与字符串子切片上使用len进行位转移产生意外输出

如何使用GRPC UnaryClientInterceptor中的`maily`参数?

GORM Find(&;Room)操作使用空数据而不是实际数据填充 struct

错误&对象已被Golang在K8s操作符上修改

正确使用pgtype的方法

如何找到一个空闲的TPM句柄来保存新的密钥对对象?

Golang:访问any类型泛型上的字段

未实现的 desc = 未知服务 pb.AuthService 我的简单身份验证服务器上出现错误

Go 中的sync.Cond 与 Wait 方法

一个Go module可以和之前的非module模块发布在同一个路径下吗?

使用 LINQ 对内部数组进行排序

加密/椭圆:try 在无效点上进行操作

Get 请求在 Thunder 客户端/Postman 中返回数据,但在 Golang 代码中给出空白数据

go-libp2p - 从流中接收字节

致命错误:找不到由 zergon321/reisen 引起的libavcodec/avcodec.h文件

如何在 golang 中同时加载 .env 文件和 os 环境变量

如何获取多个 url 参数值

具有近似约束的函数值导致的实例化失败

GOENV 只能使用 OS 环境设置