我最近换掉了数据存储,作为一个副作用,我不得不将结构字段从template.HTMLtostring更改为与 marshaller/DB 驱动程序兼容。此字段RenderedDesc包含通过russross/blackfriday传递的渲染 HTML 。
以前,我可以将整个结构“按原样”传递到模板中并调用{{ .RenderedDesc }}模板。
因为它现在是一个字符串,所以我添加了一个过滤器来将它转换回模板渲染:
模板.go
func RenderUnsafe(s string) template.HTML {
return template.HTML(s)
}
template.FuncMap{
...
"unsafe": RenderUnsafe,
}
Run Code Online (Sandbox Code Playgroud)
_content.tmpl
...
<div class="detail">
{{ .RenderedDesc | unsafe }}
</div>
...
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来实现这一点而不必在模板级别使用过滤器?缺少从我的数据库驱动程序(不在卡片上)重写编组逻辑,看起来这是“存储”字符串但呈现原始 HTML 的最简单方法。
恕我直言,正确的方法是使用过滤器,就像您已经在做的那样。有更多方法可以实现相同的目的,其中之一是使用标签并将结构转换为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,
},
}))
}
Run Code Online (Sandbox Code Playgroud)
输出:
<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>
Run Code Online (Sandbox Code Playgroud)
注意:前面的代码不适用于嵌套结构,但添加对它们的支持将很容易。此外,每个标记为不安全的字段都将被视为字符串。
| 归档时间: |
|
| 查看次数: |
753 次 |
| 最近记录: |