Go调用分页REST API出现无限循环,请求排查
分页API无限循环问题排查求助
我正在调用一个分页REST API,接口请求成功后返回如下JSON结构:
{ "hasNextPage": true, "endCursor": "some_guid_present_here" }
该API的逻辑是:通过hasNextPage判断是否存在下一页,使用endCursor作为游标继续分页查询。我之前在Python中多次调用这个API都正常,但在Go语言独立场景下实现时,偶尔会出现即使response.Paginations.HasNextPage为false,仍持续循环请求的问题。
我想排查是否是分页API调用的代码结构导致了这个问题,同时我通过goroutines发起了4-5个初始请求,不确定是否因此引发异常。目前已确认响应能正常接收并反序列化,附上核心请求逻辑代码api.go和协程调度代码etl.go,寻求问题排查帮助。
api.go
package models import ( "encoding/json" "io/ioutil" "net/http" "fmt" ) type Request struct { Url string ApiKey string } type Response struct { ...some fields... Paginations Pagination `json:"pagination"` } type Pagination struct { EndCursor string `json:"endCursor"` HasNextPage bool `json:"hasNextPage"` } func (request *Request) Get() ([]Response, error) { var responses []Response var response Response // Set up new request req, err := http.NewRequest("GET", request.Url, nil) if err != nil { fmt.Println("Error creating request...") return responses, err } // Add request headers req.Header = http.Header{ "accept": {"application/json"}, "authorization": {"Bearer " + request.ApiKey}, } // Get our initial response from the API and capture status code resp, _ := http.DefaultClient.Do(req) response.Status = resp.StatusCode // Read the response body and Unmarshal into struct respBody, err := ioutil.ReadAll(resp.Body) json.Unmarshal(respBody, &response) // If there was a parsing error, log it if err != nil { fmt.Println(err) } defer resp.Body.Close() // This field will be in the response payload // It is verified to be of type bool (not string) fmt.Printf("Has Next Page? %t\n", resp.Paginations.HasNextPage) // Append response to our slice of responses responses = append(responses, response) // If paginations are available, continue to loop through until all paginations are exhausted for response.Paginations.HasNextPage == true { req, err := http.NewRequest("GET", request.Url, nil) if err != nil { return responses, err } // Append "after" cursor to query in order to redirect to paginated response qry := req.URL.Query() qry.Set("after", response.Paginations.EndCursor) req.URL.RawQuery = qry.Encode() fmt.Println("Paginated request query: ", req.URL.String()) // Make request resp, err := http.DefaultClient.Do(req) response.Status = resp.StatusCode fmt.Printf("Status Code: %d\n", response.Status) // Read response and deserialize it respBody, err := ioutil.ReadAll(resp.Body) json.Unmarshal(respBody, &response) fmt.Println("Pagination Cursor: ", response.Paginations.EndCursor) fmt.Printf("Has Next Page? %t\n", response.Paginations.HasNextPage) // If there was a parsing error, log it if err != nil { fmt.Println(err) } defer resp.Body.Close() // Append response to our slice of responses responses = append(responses, response) } return responses, nil }
etl.go
package models import ( "fmt" "sync" ) type Etl struct { Requests []Request } func (etl *Etl) Extract() [][]Response { var wg sync.WaitGroup ch := make(chan []Response) defer close(ch) for _, req := range etl.Requests { wg.Add(1) // Increment fmt.Println("Incremented wait group") go func(i Request) { defer wg.Done() // Decrement resp, err := req.Get() if err != nil { fmt.Println(err) } ch <- resp fmt.Println("Decremented wait group") }(req) } results := make([][]Response, len(etl.Requests)) for i, _ := range results { results[i] = <-ch //fmt.Println(results[i]) } wg.Wait() return nil }
内容的提问来源于Stack Exchange,提问作者Coldchain9
相关产品推荐
相关产品推荐

