GO學習第10天(出錯處理)

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
  • 自定義用戶錯誤
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章