Golang - 避免使用未知类型的重复代码

时间:2016-10-21 22:45:14

标签: go

仍然有点新手。作为一个简单的项目,我正在尝试为Kiva's API编写一个API包装器。我试图避免编写用于处理来自API的分页响应的重复代码,但是,由于Go缺少泛型类型,我没有找到方法来执行此操作并且不确定它是否可行。

我尝试过使用类型开关和反射包来避免在多个函数中做同样的事情,但没有任何运气。这是我(完全无功能)代码的当前迭代:

type PagingData struct {
    Total    int `json: "total"`
    Page     int `json: "page"`
    PageSize int `json: "page_size"`
    Pages    int `json: "pages"`
}

type PagedLoanResponse struct {
    Paging PagingData `json: "paging"`
    Items  []Loan     `json: "loans"`
}

type PagedLenderResponse struct {
    Paging PagingData `json: "paging"`
    Items  []Lender   `json: "lenders"`
}


func (c *Client) doPaged(method string, urlpath string, query url.Values, body io.Reader, v interface{}, numPages int) ([]interface{}, error) {

    if numPages < 0 {
        return nil, fmt.Errorf("less than zero is unacceptable")
    }

    pr := reflect.New(reflect.TypeOf(v))
    if query == nil {
        query = url.Values{}
    }

    // get the first page
    err := c.do(method, urlpath, query, body, &pr)
    if err != nil {
        return nil, err
    }

    if pr.Paging.Pages == 1 {
        return pr.Items, nil
    }

    if numPages == 0 {
        numPages = pr.Paging.Pages
    }

    items := make(reflect.New(reflect.TypeOf(pr.Items)), 0, pr.Paging.Total)
    items = append(items, pr.Items...)

    for i := 2; i <= numPages; i++ {
        query.Set("page", strconv.Itoa(i))
        err := c.do("GET", urlpath, query, nil, &pr)
        if err != nil {
            return nil
        }
        items = append(items, pr.Items...)
    }

    return items, nil
}


func (c *Client) GetNewestLoans(numPages int) ([]Loan, error) {
    baseURL := "/v1/loans/newest"
    var p PagedLoanResponse
    loans, nil := c.doPaged("GET", baseURL, nil, nil, p, numPages)
}

1 个答案:

答案 0 :(得分:1)

你可以做的一件事是为任何可以分页的东西提供一个界面。也许叫Pagable

type Pagable interface { Paging() PagingData }

和实现它的单一类型:

type Pager struct { 
  Paging PagingData `json:"paging"`
}
func(p Pager) Paging() PagingData {
   return p.Paging
}

然后您的其他类型可以“嵌入”Pager以自动实施Pagable并包含这些字段:

type PagedLenderResponse struct {
    Paging
    Items  []Lender   `json: "lenders"`
}

如果doPaged然后接受Pagable代替interface{} v,则可以在其上调用Paging(),然后获取页面内容,然后json包可以将其余部分写入响应中。不需要interface{},也不需要反映。