说我有html/template
,如下所示:
<html>
<body>
<p>{{SomeFunc .SomeData}}</p>
</body>
有时SomeFunc
会返回错误。是否有一种惯用的方法来解决这个问题?
如果直接写入ResponseWriter
,则在遇到错误之前已经写入了状态代码200.
var tmpl *template.Template
func Handler(w http.ResponseWriter, r *http.Request) {
err := tmpl.Execute(w, data)
// "<html><body><p>" has already been written...
// what to do with err?
}
最好是我会返回状态代码400或其他类似内容,但如果我直接在template.Execute
上使用ResponseWriter
,我就看不到这样做的方法。我有什么遗失的吗?
答案 0 :(得分:8)
由于模板引擎即时生成输出,因此SomeFunc
调用之前的模板部分已经发送到输出。如果输出没有缓冲,则可能已经发送了它们(以及HTTP 200状态)。
你无能为力。
您可以做的是在致电template.Execute()
之前执行检查。在琐碎的情况下,调用SomeFunc()
并检查其返回值应该足够了。如果选择此路径并且SomeFunc()
的返回值很复杂,则无需再次从模板中调用它,只需将其返回值传递给传递给模板的参数并引用此值即可在模板中(所以SomeFunc()
不必执行两次)。
如果这还不够或您无法控制它,您可以创建bytes.Buffer
,执行指向此缓冲区的模板,并在Execute()
返回后检查是否有错误。如果有错误,请发回适当的错误消息/页面。如果一切顺利,您只需将缓冲区的内容发送到ResponseWriter
。
这看起来像这样:
buf := &bytes.Buffer{}
err := tmpl.Execute(buf, data)
if err != nil {
// Send back error message, for example:
http.Error(w, "Hey, Request was bad!", http.StatusBadRequest) // HTTP 400 status
} else {
// No error, send the content, HTTP 200 response status implied
buf.WriteTo(w)
}