Go服务无法从远程REST API获取全部JSON数据求助
搞定Go客户端拿不到远程API完整JSON数据的问题
嘿,我看了你的代码,结合GitHub API的特性,大概率是这几个坑导致你拿不到全部数据,咱们一个个来解决:
1. 必须处理GitHub API的分页机制!
GitHub的搜索类API默认只返回30条结果,哪怕响应里的total_count显示有几百条,默认请求也只会给你第一页的30条。你得手动循环请求所有分页才能拿到完整数据:
// 示例:遍历所有分页获取完整数据 var allItems []Item page := 1 perPage := 100 // GitHub允许的最大每页条数,能减少请求次数 baseURL := url // 你的原始API URL for { // 拼接分页参数 reqURL := fmt.Sprintf("%s?page=%d&per_page=%d", baseURL, page, perPage) res, err := netClient.Get(reqURL) if err != nil { log.Fatalf("请求分页%d失败: %v", page, err) } // 千万别忘了关闭响应体,否则会造成连接泄漏! defer res.Body.Close() var pageData JSONData if err := json.NewDecoder(res.Body).Decode(&pageData); err != nil { log.Fatalf("解码分页%d数据失败: %v", page, err) } // 把当前页的条目合并到总列表里 allItems = append(allItems, pageData.Items...) // 判断是否到最后一页:如果返回的条目数小于perPage,说明没有更多数据了 if len(pageData.Items) < perPage { break } page++ } // 组装完整的结果 fullData := JSONData{ Count: len(allItems), // 或者直接用pageData.Count(也就是接口返回的total_count) Username: user, Items: allItems, } fmt.Println(fullData)
2. 漏掉了关键的defer res.Body.Close()
你的代码里没有关闭响应体,这会导致HTTP连接泄漏,时间长了会耗尽连接池,甚至影响后续请求的响应读取。拿到响应后第一时间加上这行:
res, getErr := netClient.Get(url) if getErr != nil { log.Fatal(getErr) } defer res.Body.Close() // 这行必须加!
3. 超时设置的小矛盾
你给net.Dialer设了50秒超时,但http.Client的Timeout是40秒——这个Client的超时是整个请求生命周期的总超时(包括连接、发送请求、读取响应),所以它会覆盖Dialer的超时。如果你的API响应比较慢,40秒可能不够,建议调大一点:
var netClient = &http.Client{ Timeout: time.Second * 60, // 延长总超时到60秒 Transport: netTransport, }
另外,还可以给Transport加个ResponseHeaderTimeout,确保读取响应头的时间足够:
var netTransport = &http.Transport{ Dial: (&net.Dialer{ Timeout: 50 * time.Second, }).Dial, TLSHandshakeTimeout: 50 * time.Second, ResponseHeaderTimeout: 50 * time.Second, // 新增:等待响应头的超时时间 }
4. 调试小技巧:先看原始响应
如果还是搞不定,先把API返回的原始JSON打印出来,看看是API没给全,还是解码出了问题:
res, getErr := netClient.Get(url) if getErr != nil { log.Fatal(getErr) } defer res.Body.Close() // 读取完整的响应体 bodyBytes, err := io.ReadAll(res.Body) if err != nil { log.Fatal(err) } // 打印原始JSON,确认返回内容是否完整 fmt.Println("原始响应内容:", string(bodyBytes)) // 再进行解码操作 var data JSONData if err := json.Unmarshal(bodyBytes, &data); err != nil { log.Fatal(err) }
这样你就能清楚看到,是API本身只返回了部分数据,还是解码过程中出了问题。
内容的提问来源于stack exchange,提问作者Daniel Oluojomu
相关产品推荐
相关产品推荐

