为刚刚写的web服务器添加错误处理
go
package main
import (
"html/template"
"log"
"net/http"
"os"
)
type Page struct {
Title string
Body []byte
}
func (p *Page) save() error {
filename := p.Title + ".txt"
return os.WriteFile(filename, p.Body, 0600)
}
func loadPage(title string) (*Page, error) {
filename := title + ".txt"
body, _ := os.ReadFile(filename)
return &Page{Title: title, Body: body}, nil
}
// 由于该段代码在多个地方被重复使用,因此我们将它们提取到一个单独的函数中,以避免代码重复。
// 现在在里面添加错误处理
func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
t, err := template.ParseFiles(tmpl + ".html")
// t.Execute(w, p) 这条代码挪到后面执行,接下来先处理模板解析的错误
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
err = t.Execute(w, p) // Execute 只有一个返回值,所以也不用模式匹配了,直接用单个 err 接收就行了
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) // 500
return
}
}
func viewHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[len("/view/"):]
p, _ := loadPage(title)
renderTemplate(w, "view", p)
}
func editHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[len("/edit/"):]
p, err := loadPage(title)
if err != nil {
// p = &Page{Title: title, Body: []byte{}}
// 如果页面不存在,重定向到编辑页面
http.Redirect(w, r, "/edit/"+title, http.StatusFound)
}
// fmt.Fprintf(w, "<h1>Editing %s</h1>"+
// "<form action=\"/save/%s\" method=\"POST\">"+
// "<textarea name=\"body\">%s</textarea><br>"+
// "<input type=\"submit\" value=\"Save\">"+
// "</form>",
// p.Title, p.Title, p.Body)
// 使用template包来渲染HTML模板
// t, _ := template.ParseFiles("edit.html")
// t.Execute(w, p)
// 使用renderTemplate函数来渲染HTML模板
renderTemplate(w, "edit", p)
}
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)
}
func main() {
http.HandleFunc("/view/", viewHandler)
http.HandleFunc("/edit/", editHandler)
http.HandleFunc("/save/", saveHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}