defer + panic + recover
package main
import (
"./fileList"
"github.com/gpmgo/gopm/modules/log"
"net/http"
"os"
)
type appHaber func(writer http.ResponseWriter,
request *http.Request) error
func appWrapper(app appHaber) func(http.ResponseWriter,
*http.Request) {
return func(writer http.ResponseWriter,
request *http.Request) {
defer func() {
if r := recover(); r != nil {
log.Warn("ERROR:", r)
http.Error(writer,
http.StatusText(http.StatusInternalServerError),
http.StatusInternalServerError)
}
}()
err := app(writer, request)
if err != nil {
log.Warn("Error:%s", err.Error())
if userErr, ok := err.(userErr); ok {
http.Error(writer,
userErr.Message(),
http.StatusBadRequest)
return
}
code := http.StatusOK
switch {
case os.IsNotExist(err):
code = http.StatusNotFound
default:
code = http.StatusInternalServerError
}
http.Error(writer, http.StatusText(code), code)
}
}
}
type userErr interface {
error
Message() string
}
func main() {
http.HandleFunc("/",
appWrapper(fileList.FileList))
err := http.ListenAndServe(":8080", nil)
if err != nil {
panic(err)
}
}
package fileList
import (
"io/ioutil"
"net/http"
"os"
"strings"
)
const prefix = "/list/"
type userErr string
func (e userErr) Error() string {
return e.Message()
}
func (e userErr) Message() string {
return string(e)
}
func FileList(writer http.ResponseWriter,
request *http.Request) error {
if strings.Index(request.URL.Path, prefix) != 0 {
return userErr("Path must start with " + prefix)
}
path := request.URL.Path[len(prefix):]
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
all, err := ioutil.ReadAll(file)
if err != nil {
return err
}
_, _ = writer.Write(all)
return nil
}
- 尽可能使用error,不适用panic
- 自定义用户错误