我正在制作一个需要获取分页结果的 JSON API 包装客户端,其中下一页的 URL 由上一页提供。为了减少共享相同响应格式的 100 多个实体的代码重复,我希望有一个客户端方法来获取和解组所有分页页面中的不同实体。
我目前在简化(伪)版本中的方法(没有错误等):
type ListResponse struct {
Data struct {
Results []interface{} `json:"results"`
Next string `json:"__next"`
} `json:"d"`
}
func (c *Client) ListRequest(uri string) listResponse ListResponse {
// Do a http request to uri and get the body
body := []byte(`{ "d": { "__next": "URL", "results": []}}`)
json.NewDecoder(body).Decode(&listResponse)
}
func (c *Client) ListRequestAll(uri string, v interface{}) {
a := []interface{}
f := c.ListRequest(uri)
a = append(a, f.Data.Results...)
var next = f.Data.Next
for next != "" {
r := c.ListRequest(next)
a = append(a, r.Data.Results...)
next = r.Data.Next
}
b, _ := json.Marshal(a)
json.Unmarshal(b, v)
}
// Then in a method requesting all results for a single entity
var entities []Entity1
client.ListRequestAll("https://foo.bar/entities1.json", &entities)
// and somewehere else
var entities []Entity2
client.ListRequestAll("https://foo.bar/entities2.json", &entities)
然而问题是这种方法效率低下并且使用了太多的内存等,即首先在一般情况下解组ListResponse
,结果为[]interface{}
(查看下一个 URL 并将结果连接到单个切片中),然后将其编组以[]interface{}
直接在后面解组的目标切片[]Entity1
。
我也许可以使用该reflect
包动态地制作这些实体的新切片,直接解组它们并在之后连接/附加它们,但是如果我理解正确,reflect
除非绝对必要,否则我最好不要使用......