上一章节中,我们将对应的编辑以及查看的页面页面操作写完成了,接下来我们就是对其进行完善。
代码编写
在我们的程序中有几个地方错误被忽略了。这是一种不好的实践,尤其是因为当错误发生时,程序将产生意想不到的行为。更好的解决方案是处理错误并向用户返回错误消息。这样,如果出现错误,服务器将按照我们希望的方式运行,并通知用户。
func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
t, err := template.ParseFiles(tmpl + ".html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
err = t.Execute(w, p)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
http.Error函数发送指定的HTTP响应代码(在本例中为“内部服务器错误”)和错误消息。把它放到一个单独的函数中已经得到了返回。
现在让我们修复saveHandler:
func saveHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[len("/save/"):]
body := r.FormValue("body")
p := &Page{Title: title, Body: []byte(body)}
err := p.save()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/view/"+title, http.StatusFound)
}
在p.save()期间发生的任何错误都会报告给用户。
以上这段代码的效率不高:renderTemplate每次渲染页面时都调用ParseFiles。更好的方法是在程序初始化时调用ParseFiles,将所有模板解析为单个*模板。然后,我们可以使用ExecuteTemplate方法来呈现特定的模板。
首先,我们创建一个名为templates的全局变量,并使用ParseFiles初始化它。
var templates = template.Must(template.ParseFiles("edit.html", "view.html"))
template.Must是一个方便的包装器,当传入一个非nil的错误值时,程序会进行包裹,否则会不加修改地返回模板。在这里是合适的;如果模板不能被加载,唯一明智的做法是退出程序。
ParseFiles函数接受任意数量的字符串参数,这些参数标识我们的模板文件,并将这些文件解析为以基文件名命名的模板。如果要向程序中添加更多模板,则需要将它们的名称添加到ParseFiles调用的参数中。
然后我们修改renderTemplate函数来调用模板。带有相应模板名称的ExecuteTemplate方法:
func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
err := templates.ExecuteTemplate(w, tmpl+".html", p)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
注意,模板名称是模板文件名,所以我们必须在tmpl参数后附加.html。
总结
本节主要介绍了一个如何将我们的页面模块应用性增加,面对未知发生的错误,我们尽可能的去规避。