仍然有点新手。作为一个简单的项目,我正在尝试为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)
}
答案 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{}
,也不需要反映。