抽象 GET、读取、解组逻辑

Abstract GET, read, unmarshal logic away

我的应用程序进行了很多 API 次调用,我正试图消除与此相关的一些重复。从概念上讲,每次都会重复以下步骤:

  1. 发出 GET 请求
    1. 检查错误
  2. 阅读回复正文
    1. 检查错误
  3. 反序列化为目标结构
    1. 检查错误
  4. 返回目标结构

所有调用之间的唯一显着区别是目标结构。 在代码中它看起来像这样:

func getUsers() ([]User, error) {
    resp, err := http.Get(someUrl)
    if err != nil {
        return nil, err 
    }
    if resp.StatusCode != 200 {
        return nil, errors.New("Search return non 200 status code")
    }

    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err 
    }

    var users []User // This is the only real difference!
    err = json.Unmarshal(body, &users)
    if err != nil {
        return nil, err 
    }

    return users, nil 
}

我很想做类似 getUsers(url, users)getProjects(url, projects) 的事情。

我一直在尝试使用一个接受 interface{} 的函数,稍后再将其转换为正确的类型,但无济于事:

func request(url string, target interface{}) (interface{}, error) {
     // do all the same logic as above. Except:
     err = json.Unmarshal(body, &target)
     // ...
     return target, nil
}

然后做类似的事情:

 var users []User
 result, err := request(url, users)
 v, ok := result.([]User)

我觉得这应该是可能的...

不要使用 interface{} 的地址,它已经包含解组所需的指针。

func request(url string, target interface{}) (interface{}, error) {
     // get response
     err = json.Unmarshal(body, target)
    ...

example