在下面的代码中:
func (p *ProductHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// handle the request for a list of products
if r.Method == http.MethodGet {
p.getProductHandler(w, r)
return
}
if r.Method == http.MethodPost {
p.addProductHandler(w, r)
return
}
if r.Method == http.MethodPut {
id := findID(w, r)
p.updateProductHandler(id, w, r)
return
}
// catch all
// if no method is satisfied return an error
w.WriteHeader(http.StatusMethodNotAllowed)
}
// getProducts returns the products from the data store
func (p *ProductHandler) getProductHandler(w http.ResponseWriter, r *http.Request) {
p.l.Println("Handle GET Products")
// fetch the products from the datastore
productList := data.GetProducts()
// serialize the list to JSON
err := productList.WriteJSON(w)
if err != nil {
http.Error(w, "Unable to marshal json", http.StatusInternalServerError)
return
}
}
func (p *ProductHandler) addProductHandler(w http.ResponseWriter, r *http.Request) {
p.l.Println("Handle POST products")
// Read the item from the incoming request
productItem := &data.Product{}
err := productItem.ReadJSON(r.Body)
if err != nil {
http.Error(w, "Unable to unmarshal JSON", http.StatusBadRequest)
return
}
p.l.Printf("Product item: %#v\n", productItem)
data.AddProductItem(productItem)
}
func (p *ProductHandler) updateProductHandler(id int, w http.ResponseWriter, r *http.Request) {
// whatever
return
}
func findID(w http.ResponseWriter, r *http.Request) int {
// expect the id in the URI
dfa := regexp.MustCompile(`/([0-9]+)`)
matches := dfa.FindAllStringSubmatch(r.URL.Path, -1) // returns [][]string
if len(matches) != 1 {
http.Error(w, "Invalid URI", http.StatusBadRequest)
return
}
if len(matches[0]) != 2 {
http.Error(w, "Invlaid URI", http.StatusBadRequest)
return
}
idString := matches[0][1]
id, err := strconv.Atoi(idString)
if err != nil {
http.Error(w, "Invlaid URI", http.StatusBadRequest)
return
}
return id
}
发生错误时,我们在处理
http.Error()
和POST
以及GET
的处理程序中使用return
但是对于
PUT
请求,调用堆栈堆栈是ServeHTTP
-> findID(),然后是ServeHTTP()
-> updateProductHandler()
。 findID()
中需要进行错误处理,但由于findID()
返回int,因此无法立即返回。对调用堆栈执行错误处理的设计模式是什么?使用
github.com/pkg/errors
包装错误....
最佳答案
func (p *ProductHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// handle the request for a list of products
if r.Method == http.MethodGet {
p.getProductHandler(w, r)
return
}
if r.Method == http.MethodPost {
p.addProductHandler(w, r)
return
}
if r.Method == http.MethodPut {
id, err := findID(r.URL.Path)
if err == nil {
p.updateProductHandler(id, w, r)
} else {
http.Error(w, err.Error(), http.StatusBadRequest)
}
return
}
// catch all
// if no method is satisfied return an error
w.WriteHeader(http.StatusMethodNotAllowed)
w.Header().Add("Allow", "GET, POST, PUT")
}
func findID(path string) (int, error) {
// expect the id in the URI
dfa := regexp.MustCompile(`/([0-9]+)`)
matches := dfa.FindAllStringSubmatch(path, -1) // returns [][]string
if len(matches) != 1 {
return 0, fmt.Errorf("Invalid URI %s", path)
}
if len(matches[0]) != 2 {
return 0, fmt.Errorf("Invalid URI %s", path)
}
idString := matches[0][1]
id, err := strconv.Atoi(idString)
if err != nil {
return 0, fmt.Errorf("Invalid URI %s", path)
}
return id, nil
}
关于http - 调用堆栈上的错误处理-HTTP请求处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62441777/