【发布时间】:2016-10-03 06:07:06
【问题描述】:
假设一个 Go 程序有几个像这样的处理函数:
type FooRequest struct {
FooField string `json:"foofield"`
// ...
}
type FooResponse struct {
BarField string `json:"barfield"`
// ...
}
func handleFoo(w http.ResponseWriter, r *http.Request) {
var req FooRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// do what actually matters:
foo := DoStuff(req)
baz, err := DoSomething(foo)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
resp := DoEvenMoreStuff(baz)
// back to boiler plate:
if err := json.NewEncoder(w).Encode(resp); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
如何重构此代码以避免 JSON 解码/编码样板?
我可能希望看到一个通用的“处理 JSON”func 和另一个处理实际 foo 内容的 func:
func handleJson(w http.ResponseWriter, r *http.Request) {
var req FooRequest // what about this line?
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
resp, err := handleFooElegantly(req)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := json.NewEncoder(w).Encode(resp); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func handleFoo(req FooRequest) (FooResponse, error) {
var resp FooResponse
foo := DoStuff(req)
baz, err := DoSomething(foo)
if err != nil {
return resp, err
}
resp = DoEvenMoreStuff(baz)
return resp, nil
}
这给我们留下了告诉 JSON 解码器它应该尝试解码的类型的问题。
实现这一点的惯用 Go 方式是什么?
【问题讨论】: