【问题标题】:golang templates processing and genericsgolang 模板处理和泛型
【发布时间】:2017-09-05 10:10:30
【问题描述】:

我有两个golang html模板,如下:

var m map[string]string
m = make(map[string]string)

m["First"] = `<html>
<body>First template type {{.First}}
</html>`

m["Second"] = `<html>
<body>Second template type {{.SecondF1}} {{.SecondF2}}
</html>`

第一个 html 模板只需要一个参数,名为 First,而第二个模板需要两个参数,名为 SecondF1SecondF2

现在我有一个结构体,它有两个字段,一个用于接收模板名称,另一个用于接收模板参数。

type tmplReceiver struct {
    TmplName string
    TmplArgs string // Receives JSON string
}

现在,上述结构的实例示例如下:

var i, j tmplReceiver

i.TmplName = "First"
i.TmplArgs = `{"Field1": "First Template Argument"}`

j.TmplName = "Second"
j.TmplArgs = `{
  "SecondF1": "Second template First Argument", 
  "SecondF2": "Second template Second Argument"
}`

现在我可以使用地图获取模板字符串,例如:

tmplStr := m[i.TmplName] (or)
tmplStr := m[j.TmplName]

tmpl, _ = template.New("email").Parse(tmplStr)

但是,如何使用单个tmpl.Execute 语句为所有可能的模板类型执行模板。换句话说,如果我想拥有以下代码:

var buff bytes.Buffer
if err := tmpl.Execute(&buff, tmplPtr); err != nil {
    log.Fatal(err)
}
log.Println(buff.String())

如何让tmplPtr 有效,无论我有多少模板(FirstSecond 等),并且每个模板都可以有可变数量的参数(First只有一个参数,而Second 有两个参数,等等)

我不想为每个模板名称编写 N 个不同的 tmpl.Execute 语句,并带有 if 块。有没有其他替代方法来解决这个问题?谢谢。

【问题讨论】:

    标签: templates go


    【解决方案1】:

    json.Unmarshaltemplate.Execute 都不关心数据的实际类型,这都将在运行时处理。因此,您可以将 json 解析为 interface{} 并将其传递给您的模板。假设 json 数据包含您将数据传递到的模板所期望的字段,这将正常工作。

    Playground link

    package main
    
    import (
        "bytes"
        "encoding/json"
        "fmt"
        "html/template"
    )
    
    var templates = map[string]*template.Template{
        "A": template.Must(template.New("A").Parse("{{ .A }}")),
        "B": template.Must(template.New("B").Parse("{{ .B }} and {{ .C.D }}")),
    }
    
    type tmplReceiver struct {
        TmplName string
        TmplArgs string
    }
    
    func main() {
        receivers := []tmplReceiver{
            tmplReceiver{"A", `{"A": "Value for A"}`},
            tmplReceiver{"B", `{"B": "Value for B", "C": { "D": "Value for D" }}`},
        }
    
        for _, receiver := range receivers {
            var data interface{}
            json.Unmarshal([]byte(receiver.TmplArgs), &data)
    
            var buffer bytes.Buffer
            templates[receiver.TmplName].Execute(&buffer, data)
            fmt.Println(buffer.String())
        }
    }
    

    打印出来的

    A 的价值

    B 的价值和 D 的价值

    【讨论】:

    • 但我希望它作为 HTTP 处理程序的一部分,其中输入也将来自其他语言。所以我需要一个没有接口或映射的 JSON 结构。
    • @SankarP 我不确定我是否理解您的评论,但在我更新的答案中,无论结构如何,您都可以处理任何传入的 json,并在模板中使用它。唯一的要求是数据包含您要在模板中使用的字段,但无论如何都无法避免。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 2014-04-29
    • 2018-01-13
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 2012-10-09
    相关资源
    最近更新 更多