Go template.ExecuteTemplate包含html

Go template.ExecuteTemplate包含html,go,go-templates,Go,Go Templates,我遵循了本教程:并根据我的需要对其进行了轻微修改。问题是我想在模板中支持HTML。我意识到这是一种安全风险,但目前还不担心 页面呈现的结果: <h1>this<strong>is</strong>a test</h1> 我想要的HTML数据存储在Page.Body中。这是类型[]byte,这意味着我不能(或者可以?)运行html/template.html(Page.Body),因为该函数需要一个字符串 我有一个预渲染模板的程序: var (

我遵循了本教程:并根据我的需要对其进行了轻微修改。问题是我想在模板中支持HTML。我意识到这是一种安全风险,但目前还不担心

页面呈现的结果:

<h1>this<strong>is</strong>a test</h1>
我想要的HTML数据存储在
Page.Body
中。这是类型
[]byte
,这意味着我不能(或者可以?)运行
html/template.html(Page.Body)
,因为该函数需要一个字符串

我有一个预渲染模板的程序:

var (
    templates = template.Must(template.ParseFiles("tmpl/edit.html", "tmpl/view.html"))
)
实际的
ExecuteTemplate
如下所示:

err := templates.ExecuteTemplate(w, tmpl+".html", p)
str := string(page.Body)
其中w是http.ResponseWriter
w,tmpl是
tmpl字符串
,p是
p*Page

最后,我的
'view.html'
(模板)如下所示:

<h1>{{.Title}}</h1>
<p>[<a href="/edit/{{.Title}}">edit</a>]</p>
<div>{{printf "%s" .Body}}</div>
{{.Title}
[]

{{printf“%s”.Body}
我尝试过的事情:

  • {{printf“%s”.Body | html}}
    没有任何作用
  • 我已经包括了
    github.com/russross/blackfriday
    (Markdown处理器),并运行了
    p.Body=blackfriday.markdowncomon(p.Body)
    ,它正确地将Markdown转换为HTML,但HTML仍然作为实体输出
  • 编辑:我尝试了以下代码(我不知道为什么格式会出错),但它仍然输出完全相同的结果

    var s template.HTML
    s=template.HTML(p.Body)
    p.Body=[]字节


非常感谢您的指导。如果我感到困惑,请提问,我可以修改我的问题。

为什么不将
[]字节转换为字符串?您可以这样做:

err := templates.ExecuteTemplate(w, tmpl+".html", p)
str := string(page.Body)

[]字节
字符串
转换为类型
template.HTML
(有文档记录)

然后,在模板中,只需:

{{.Body}}
它将被打印而不会转义

编辑

为了能够在页面正文中包含HTML,您需要更改
页面
类型声明:

type Page struct {
    Title string
    Body  template.HTML
}
然后分配给它。

查看类型。它可以用来封装已知的HTML安全片段(如Markdown的输出)。“html/template”包不会转义此类型

type Page struct {
    Title string
    Body template.HTML
}

page := &Page{
    Title: "Example",
    Body:  template.HTML(blackfriday.MarkdownCommon([]byte("foo bar")),
}
我通常编写自己的
func Markdown(text string)html.Template
方法,用适当的配置调用blackfriday并进行一些类型转换。另一种选择可能是在模板解析器中注册一个“html”func,它允许您通过执行类似于
{{html.MySafeStr}}
的操作来输出任何值而不进行任何转义。代码可能如下所示:

var tmpl = template.Must(template.New("").Funcs(template.FuncMap{
    "html": func(value interface{}) template.HTML {
        return template.HTML(fmt.Sprint(value))
    },
}).ParseFiles("file1.html", "file2.html"))

我使用Beego和React.js,花了几个小时试图让JSX解析器运行。结果是html/模板去掉了注释,尤其是js doc block/**@jsx React.DOM*/

通过创建一个特殊的方法将注释输入为JS并在模板中调用它,解决了这个问题

// Create a method in your controller (I'm using Beego)
func jsxdoc()(out template.JS) {
    return template.JS(`/** @jsx React.DOM */`)
}

// Add method to your function map available to views
beego.AddFuncMap("jsxdoc", jsxdoc)

// In template
<script type="text/jsx">
    {{ jsxdoc }}
    var CommentBox = React.createClass({
      render: function() {
        return (
          <div class="commentBox">
            Hello, world! I am a CommentBox.
          </div>
        );
      }
    });
    React.renderComponent(
      <CommentBox />,
      document.getElementById('content')
    );
</script>
//在控制器中创建一个方法(我正在使用Beego)
func jsxdoc()(out template.JS){
返回template.JS(`/**@jsx React.DOM*/`)
}
//将方法添加到视图可用的函数映射中
AddFuncMap(“jsxdoc”,jsxdoc)
//模板中
{{jsxdoc}}
var CommentBox=React.createClass({
render:function(){
返回(
你好,世界!我是一个评论箱。
);
}
});
React.renderComponent(
,
document.getElementById('content')
);

有关向模板传递HTML的说明和更简单的方法,请参阅

只需通过go创建HTML字符串并将其传递到模板中,例如:

Sout := ""
.
.

    Sout += fmt.Sprintf(`<tr><td>%s<td align=center>%.2f<td>%s<td>%s<td>%s<td>%s<td align=center>%d<td align=center>%d
                    <td align=center>%d`, AccountID, amount, remissiondetails, created, begins, ends,
                    freePDFs, freeinformants, freeSDQs)

.
.
    render(w, "templates/Waivers.html", map[string]interface{}{ "Body":template.HTML(Sout), })
Sout:=“”
.
.
Sout+=fmt.Sprintf(`%s%.2f%s%s%s%s%d%d
%d`、帐户ID、金额、减免明细、创建、开始、结束、,
免费PDF、免费线人、免费DQ)
.
.
render(w,“templates/averages.html”,map[string]接口{}{“Body”:template.html(Sout),})

我为模板创建了一个自定义函数,如下所示:

func noescape(str string) template.HTML {
    return template.HTML(str)
}

var fn = template.FuncMap{
    "noescape": noescape,
}
然后在模板上:

{{ noescape $x.Body }}

这是一种不需要对现有结构进行任何更改的方法,并且只需对模板进行非常小的附加更改:

var (
    templates = template.Must(template.ParseFiles("tmpl/edit.html", "tmpl/view.html"))
)
更改这些行:

var (
    templates = template.Must(template.ParseFiles("tmpl/edit.html", "tmpl/view.html"))
)
为此(包括一个funcmap,其中包含一个将输出未转义HTML的函数):

然后只需从以下内容更改模板HTML:

<div>{{printf "%s" .Body}}</div>
{{printf“%s”.Body}
为此(使用新功能):

{{.Body|safeHTML}

容易多了

在我的例子中(我用
活动的列表填充视图
结构
),我必须将属性
消息字符串
更改为
消息模板.HTML
。然后,当设置属性值时,我可以调用
activity.Message=template.HTML(“HTML”)

我尝试过,问题是
模板。ExecuteTemplate
需要一个指向页面的指针,该指针要求它是
[]字节
我尝试了完全按照您所说的做,并收到以下错误:
无法使用字符串(p.Body)(type string)作为赋值中的[]字节类型
。同样,将我的结构更改为使用字符串而不是[]字节会在将内容保存到文件时导致其他问题。这不起作用。我收到以下消息:
无法将“html/template.html(p.Body)(type“html/template.html”)作为[]类型使用分配中的字节
不要只是复制粘贴并说它不起作用。显然,您需要更改正文字段的类型,以便能够将template.HTML类型的内容分配给它。请参阅我昨晚在发布评论后对我的问题所做的编辑。我确实更改了正文的类型,但我仍然看到了确切的sam我添加了一个名为“noescape”的函数,该函数将字符串转换为
template.HTML
,然后在管道中将
printf
转换为字符串。这个函数非常神奇。我花了几天的时间对我的模板感到非常生气,因为我通过了它
<div>{{ .Body | safeHTML }}</div>