我最近交换了数据存储,作为副作用,我不得不将struct字段从template.HTML更改为string,以便与封送处理/DB驱动程序兼容。此字段RenderedDesc包含通过纵横交错/黑日传递的呈现的HTML。
以前,我只需将整个结构传递到模板“原样”中,并在模板中调用{{ .RenderedDesc }}。
因为它现在是一个字符串,所以我添加了一个过滤器来在模板呈现中将其转换回来:
templates.go
func RenderUnsafe(s string) template.HTML {
    return template.HTML(s)
}
template.FuncMap{
        ...
        "unsafe": RenderUnsafe,
    }_content.tmpl
...
<div class="detail">
    {{ .RenderedDesc | unsafe }}
</div>
...是否有更好的方法来实现这一点而不必在模板级别使用过滤器?除了从我的DB驱动程序重写编组逻辑(不在卡片上)外,这看起来是“存储”字符串但呈现原始HTML的最简单方法。
发布于 2014-01-29 15:44:26
IMHO,正确的方法是使用过滤器,就像你已经在做的那样。实现相同目标的方法有很多,其中之一是使用标记并将结构转换为map[string]Interface{}。因为可以以与结构相同的方式访问映射字段,所以模板将保持不变。
向我展示代码(游乐场):
package main
import (
    "html/template"
    "os"
    "reflect"
)
var templates = template.Must(template.New("tmp").Parse(`
    <html>
        <head>
        </head>
        <body>
            <h1>Hello</h1>
            <div class="content">
                Usafe Content = {{.Content}}
                Safe Content  = {{.Safe}}
                Bool          = {{.Bool}}
                Num           = {{.Num}}
                Nested.Num    = {{.Nested.Num}}
                Nested.Bool   = {{.Nested.Bool}}
            </div>
        </body>
    </html>
`))
func asUnsafeMap(any interface{}) map[string]interface{} {
    v := reflect.ValueOf(any)
    if v.Kind() != reflect.Struct {
        panic("asUnsafeMap invoked with a non struct parameter")
    }
    m := map[string]interface{}{}
    for i := 0; i < v.NumField(); i++ {
        value := v.Field(i)
        if !value.CanInterface() {
            continue
        }
        ftype := v.Type().Field(i)
        if ftype.Tag.Get("unsafe") == "html" {
            m[ftype.Name] = template.HTML(value.String())
        } else {
            m[ftype.Name] = value.Interface()
        }
    }
    return m
}
func main() {
    templates.ExecuteTemplate(os.Stdout, "tmp", asUnsafeMap(struct {
        Content string `unsafe:"html"`
        Safe    string
        Bool    bool
        Num     int
        Nested  struct {
            Num  int
            Bool bool
        }
    }{
        Content: "<h2>Lol</h2>",
        Safe:    "<h2>Lol</h2>",
        Bool:    true,
        Num:     10,
        Nested: struct {
            Num  int
            Bool bool
        }{
            Num:  9,
            Bool: true,
        },
    }))
}输出:
<html>
    <head>
    </head>
    <body>
        <h1>Hello</h1>
        <div class="content">
            Usafe Content = <h2>Lol</h2>
            Safe Content  = <h2>Lol</h2>
            Bool          = true
            Num           = 10
            Nested.Num    = 9
            Nested.Bool   = true
        </div>
    </body>
</html>注意:前面的代码不适用于嵌套结构,但是添加对它们的支持很容易。此外,标记为不安全的每个字段都将被视为字符串。
https://stackoverflow.com/questions/21433920
复制相似问题