Still a bit of a go newb. As a simple project, I'm trying to write an API wrapper for Kiva's API. I'm trying to avoid writing duplicate code for handling paged responses from the API, but, given Go's lack of generic types, I haven't found a way to do it and am not sure if it's possible.
I've tried using type switches and the reflect package to avoid doing the exact same thing in multiple functions but haven't had any luck. This is the current iteration of my (totally non-functional) code:
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)
}