You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 09:06:38