2017-03-02 90 views
0

我有这个简单的通用要求结构使GET请求在我的应用程序:如何使函数适用于不同的输入类型?

package api 

import (
    "net/http" 
    "time" 
    "log" 
    "app/errors" 
) 

type Request struct { 
    Url string 
} 

func (request *Request) Run(responseObject *AppStatusInfo) *errors.Error { 

    req, requestErr := http.NewRequest(http.MethodGet, request.Url, nil) 

    req.Header.Set("Content-Type", "application/json") 

    timeout := time.Duration(5 * time.Second) 

    client := &http.Client{ 
     Timeout: timeout, 
    } 

    resp, requestErr := client.Do(req) 

    if requestErr != nil { 
     return &errors.UnknownError 
    } 

    decodeError := DecodeJsonRequestBody(resp, &responseObject) 

    if (decodeError != nil) { 
     return &errors.UnknownError 
    } 

    defer resp.Body.Close() 

    return nil 
} 

这里responseObject有型AppStatusInfo的指针是一些字段的结构。

我运行像这样得到应用的状态信息,并把它里面appStatusInfo对象:

var appStatusInfo AppStatusInfo 

req := Request{ 
    Url:config.Config.ApiUrl, 
} 

req.Run(&appStatusInfo) 

因此,该代码运行正常。

但是,当我想概括请求中接受其他类型的响应,像UserProducts,我不知道该怎么做,而不与responseObject interface{}更换responseObject *AppStatusInfo,然后用responseObject铸造它。(UserProducts),我觉得可以改进。

因此,只要没有泛型,我如何让Request.Run()接受不同的类型并返回相应的对象?

+0

很确定空接口是你唯一的选择。 –

回答

1

假设DecodeJsonRequestBody将第二个参数传递给json.Unmarshaljson.Decoder.Decode,然后像这样写出来。我只显示更改的行:

func (request *Request) Run(responseObject interface{}) *errors.Error { 
    ... 
    resp, requestErr := client.Do(req) 
    if requestErr != nil { 
     return &errors.UnknownError 
    } 
    defer resp.Body.Close() // defer close before doing anything else 
    ... 
    decodeError := DecodeJsonRequestBody(resp, responseObject) // don't take address of responseObject 
    ... 
} 

你可以这样调用:

var up UserProducts 
err = r.Run(&up) 

var asi AppStatusInfo 
err = r.Run(&asi) 

类型的断言和类型转换不是必需的。

相关问题