Golang函数指定超过700条数据量时返回空切片问题求助
Alright, let's dig into this head-scratcher of an issue—super confusing when the inner function sees valid data but the caller gets an empty slice, right? Let's break down the likely causes and fixes step by step.
The Top Suspect: Ignored Errors & Unclosed Resources
First, let's look at two critical oversights in your code that are almost certainly causing this behavior when your count exceeds 700:
1. You're Ignoring Errors in the Caller
In WriteProducts, you're discarding the error returned by LoadProducts:
products, _ := d.scrapperService.LoadProducts(702, 1, token)
When dealing with larger datasets, things like HTTP timeouts, API rate limits, or malformed responses become far more likely—but you're not checking for these errors. If LoadProducts hits an error, it returns nil, err, which means products will be an empty slice even if the inner log showed data.
2. You're Not Closing the HTTP Response Body
In LoadProducts, you never close the response body after using it. For large payloads, leaving the body unclosed can cause unexpected behavior: the JSON decoder might not finish reading the full response before the function returns, or you could hit connection limits that break subsequent requests. The Go docs explicitly require closing the response body, even if you don't read it.
Step-by-Step Fixes
Let's fix these issues one by one, plus add some extra safeguards to debug future problems.
First, Fix LoadProducts to Handle Errors & Close Resources
Update the function to close the response body, return early on errors, and check HTTP status codes:
func (s serviceImpl) LoadProducts(count uint, page uint, token string) ([]models.VariantsResult, error) { jsonBody := []byte(fmt.Sprintf(`{"pageSize": %d, "page": %d, "sortBy": "updatedAt"}`, count, page)) body := bytes.NewBuffer(jsonBody) // Create request, return early on error req, err := http.NewRequest("POST", fmt.Sprintf("%v/api/variantGroups/search", os.Getenv("BACKEND")), body) if err != nil { log.Printf("Failed to create request: %v", err) return nil, err } // Set headers req.Header.Add("Accept", "application/json, text/plain, */*") req.Header.Add("Authorization", fmt.Sprintf("Bearer %v", token)) req.Header.Add("Content-Type", "application/json") // Send request, return early on error resp, err := s.client.Do(req) if err != nil { log.Printf("Failed to send request: %v", err) return nil, err } defer resp.Body.Close() // Critical: close the response body when done // Check for non-success HTTP status codes (many APIs reject large page sizes) if resp.StatusCode < 200 || resp.StatusCode >= 300 { bodyBytes, _ := io.ReadAll(resp.Body) log.Printf("API returned error status %d: %s", resp.StatusCode, string(bodyBytes)) return nil, fmt.Errorf("API request failed with status %d", resp.StatusCode) } // Define response struct and decode type Response struct { Results []models.VariantsResult `json:"results"` Count int `json:"count"` } var response Response err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { log.Printf("Failed to decode JSON response: %v", err) return nil, err } log.Printf("products -> %d", len(response.Results)) return response.Results, nil }
Second, Fix the Caller to Check Errors
In WriteProducts, stop ignoring the error and handle it properly:
// Load products with error checking products, err := d.scrapperService.LoadProducts(702, 1, token) if err != nil { log.Printf("Failed to load products: %v", err) return err } log.Printf("products count -> %d", len(products))
Why This Fixes the Issue
- Unclosed response body: For large datasets, leaving the body open can prevent the decoder from finishing its work, leading to an empty slice being returned even if the API sent valid data.
- Ignored errors: You'll now see exactly what's failing when you request more than 700 items—like if the API has a maximum page size limit (common for many services) or if the request times out.
- Status code checks: This will catch cases where the API rejects your large page size with an error response, which was previously hidden.
Extra Checks to Rule Out Edge Cases
- Verify if the API has a documented maximum page size (many cap this at 500 or 700). If so, you'll need to paginate through results instead of requesting all at once.
- Ensure your
http.Clienthas a sufficient timeout for large responses:client := &http.Client{ Timeout: 30 * time.Second, // Adjust based on your API's response time }
内容的提问来源于stack exchange,提问作者Abanoub Istfanous




