我正在使用一个库(go-kit),它要求我指定函数来编码/解码我的请求和响应类型到JSON或从JSON返回。对于编码,它很简单:
func EncodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
return json.NewEncoder(w).Encode(response)
}我传递这个函数来创建HTTP服务器,它工作得很好。然而,他们提出的请求方法是为表单创建一个单独的函数:
func decodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) {
var req UppercaseRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, err
}
return req, nil
}对于我的应用程序中的每个RPC。我真的想让我的代码保持干燥,避免有数百个几乎相同的方法。因此,我尝试编写一个函数来生成对给定请求类型进行解码的闭包:
func DecodeRequest(req interface{}) httptransport.DecodeRequestFunc {
return func(_ context.Context, r *http.Request) (interface{}, error) {
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, err
}
return req, nil
}
}这个函数可以像这样调用:
DecodeRequest(UppercaseRequest{}}不幸的是,当我这样做时,JSON解码失败,即使请求类型实际上是mypackage.UppercaseRequest。我不知道下一步该怎么走。有没有一种方法可以避免必须为每个请求类型编写一个方法?有没有什么方法可以帮助Decode函数在运行时理解这个类型?提前感谢!
这是一个演示这个问题的go游乐场:https://play.golang.org/p/GgHsLffp1G
发布于 2016-08-20 21:53:31
根据您向我们展示的代码片段,我认为您正面临类型断言问题。我创建了一个playground to show you what I explain below。
您正在向DecodeRequest函数传递一个UpperCaseRequest。在此函数中,参数的类型为interface{},并将此参数的指针传递给json解码器。因此,解码器看到的是指向接口的指针,而不是指向UpperCaseRequest的指针。
这就是它没有被正确解码的原因。然后,在它上尝试类型断言失败,因为断言两个不同的类型是不可能的。
所以,在你的代码中,我建议:
func DecodeRequest(req interface{}) httptransport.DecodeRequestFunc {
return func(_ context.Context, r *http.Request) (interface{}, error) {
// Note the '&' is removed here
if err := json.NewDecoder(r.Body).Decode(req); err != nil {
return nil, err
}
return req, nil
}
}像这样调用这个函数:
// Note the & is placed here.
DecodeRequest(&UppercaseRequest{}}https://stackoverflow.com/questions/39052143
复制相似问题