当切片长度超过700个元素时,Golang函数返回空切片。

huangapple go评论123阅读模式
英文:

golang function returns empty slice when slice length more than 700 item

问题

我有一个调用API的函数来获取项目,并将项目返回以与另一个数据库同步。我可以指定返回的项目数量限制。如果限制为700,则返回700个项目。如果超过700个,则返回空切片。

  1. func (d *dataBaseWriterImpl) WriteProducts() error {
  2. username := os.Getenv("USERNAME")
  3. password := os.Getenv("PASSWORD")
  4. // 获取令牌
  5. token, err := d.authService.Login(username, password)
  6. if err != nil {
  7. return err
  8. }
  9. // 加载产品
  10. // 这里的问题是如果数量超过700 <----
  11. products, _ := d.scrapperService.LoadProducts(702, 1, token)
  12. log.Printf("产品数量 -> %d", len(products)) // 返回的是0 <-----
  13. errChan := make(chan error, 2)
  14. var cats []models.Category
  15. db.Conn.Model(&models.Category{}).Find(&cats)
  16. var catIds []string
  17. for _, cat := range cats {
  18. catIds = append(catIds, cat.ExternalId)
  19. }
  20. for _, prod := range products {
  21. if d.isValidProduct(catIds, prod.PrimaryVariant.CategoryID) {
  22. log.Printf("更新ID -> %v", prod.PrimaryVariant.ID)
  23. go d.saveOrUpdateProducts(prod.PrimaryVariant, errChan)
  24. } else {
  25. log.Printf("不会更新ID -> %v", prod.PrimaryVariant.ID)
  26. go func() {
  27. errChan <- nil
  28. }()
  29. }
  30. }
  31. for range products {
  32. err := <-errChan
  33. if err != nil {
  34. return err
  35. }
  36. }
  37. return nil
  38. }

我在返回之前记录了项目的长度,它在LoadProducts实现中返回了实际值。

  1. func (s serviceImpl) LoadProducts(count uint, page uint, token string) ([]models.VariantsResult, error) {
  2. jsonBody := []byte(fmt.Sprintf(`{"pageSize": %d, "page": %d, "sortBy": "updatedAt"}`, count, page))
  3. body := bytes.NewBuffer(jsonBody)
  4. // 创建请求
  5. req, err := http.NewRequest("POST", fmt.Sprintf("%v/api/variantGroups/search", os.Getenv("BACKEND")), body)
  6. if err != nil {
  7. log.Print(err)
  8. }
  9. // 请求头
  10. //req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:84.0) Gecko/20100101 Firefox/84.0")
  11. req.Header.Add("Accept", "application/json, text/plain, */*")
  12. req.Header.Add("Authorization", fmt.Sprintf("Bearer %v", token))
  13. req.Header.Add("Content-Type", "application/json")
  14. // 发送请求
  15. resp, err := s.client.Do(req)
  16. if err != nil {
  17. fmt.Println("失败: ", err)
  18. }
  19. //[]models.Product `json:"data"`
  20. // 读取响应
  21. type Response struct {
  22. Results []models.VariantsResult `json:"results"`
  23. Count int `json:"count"`
  24. }
  25. var response Response
  26. err = json.NewDecoder(resp.Body).Decode(&response)
  27. log.Printf("产品 -> %d", len(response.Results)) // 返回的是实际数量 <--
  28. if err != nil {
  29. return nil, err
  30. }
  31. return response.Results, nil
  32. }
英文:

I have a function calls API to get items and return items to sync with another db. I can specify limit of items that returns. If the limit is 700 it return 700 item. if more than 700 it return empty slice.

  1. func (d *dataBaseWriterImpl) WriteProducts() error {
  2. username := os.Getenv(&quot;USERNAME&quot;)
  3. password := os.Getenv(&quot;PASSWORD&quot;)
  4. // get token
  5. token, err := d.authService.Login(username, password)
  6. if err != nil {
  7. return err
  8. }
  9. // load products
  10. // here the problem if count more than 700 &lt;----
  11. products, _ := d.scrapperService.LoadProducts(702, 1, token)
  12. log.Printf(&quot;products count -&gt; %d&quot;, len(products)) // gives me 0 &lt;-----
  13. errChan := make(chan error, 2)
  14. var cats []models.Category
  15. db.Conn.Model(&amp;models.Category{}).Find(&amp;cats)
  16. var catIds []string
  17. for _, cat := range cats {
  18. catIds = append(catIds, cat.ExternalId)
  19. }
  20. for _, prod := range products {
  21. if d.isValidProduct(catIds, prod.PrimaryVariant.CategoryID) {
  22. log.Printf(&quot;update id -&gt; %v&quot;, prod.PrimaryVariant.ID)
  23. go d.saveOrUpdateProducts(prod.PrimaryVariant, errChan)
  24. } else {
  25. log.Printf(&quot;will not update id -&gt; %v&quot;, prod.PrimaryVariant.ID)
  26. go func() {
  27. errChan &lt;- nil
  28. }()
  29. }
  30. }
  31. for range products {
  32. err := &lt;-errChan
  33. if err != nil {
  34. return err
  35. }
  36. }
  37. return nil
  38. }

I log items length before return it return the actual value in the LoadProducts implementation.

  1. func (s serviceImpl) LoadProducts(count uint, page uint, token string) ([]models.VariantsResult, error) {
  2. jsonBody := []byte(fmt.Sprintf(`{&quot;pageSize&quot;: %d, &quot;page&quot;: %d, &quot;sortBy&quot;: &quot;updatedAt&quot;}`, count, page))
  3. body := bytes.NewBuffer(jsonBody)
  4. // Create request
  5. req, err := http.NewRequest(&quot;POST&quot;, fmt.Sprintf(&quot;%v/api/variantGroups/search&quot;, os.Getenv(&quot;BACKEND&quot;)), body)
  6. if err != nil {
  7. log.Print(err)
  8. }
  9. // Headers
  10. //req.Header.Add(&quot;User-Agent&quot;, &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:84.0) Gecko/20100101 Firefox/84.0&quot;)
  11. req.Header.Add(&quot;Accept&quot;, &quot;application/json, text/plain, */*&quot;)
  12. req.Header.Add(&quot;Authorization&quot;, fmt.Sprintf(&quot;Bearer %v&quot;, token))
  13. req.Header.Add(&quot;Content-Type&quot;, &quot;application/json&quot;)
  14. // Fetch Request
  15. resp, err := s.client.Do(req)
  16. if err != nil {
  17. fmt.Println(&quot;Failure : &quot;, err)
  18. }
  19. //[]models.Product `json:&quot;data&quot;`
  20. // Read Response
  21. type Response struct {
  22. Results []models.VariantsResult `json:&quot;results&quot;`
  23. Count int `json:&quot;count&quot;`
  24. }
  25. var response Response
  26. err = json.NewDecoder(resp.Body).Decode(&amp;response)
  27. log.Printf(&quot;products -&gt; %d&quot;, len(response.Results)) // gives me actual number &lt;--
  28. if err != nil {
  29. return nil, err
  30. }
  31. return response.Results, nil
  32. }

答案1

得分: 3

你几乎可以肯定是返回了一个错误,但是却忽略了它。

> 一个空切片的长度和容量为0,并且没有底层数组。https://tour.golang.org/moretypes/12

你在这里返回了 nil, err:

  1. // 在 LoadProducts 中
  2. if err != nil {
  3. return nil, err
  4. }

但是接下来却这样做了:

  1. products, _ := d.scrapperService.LoadProducts(702, 1, token)
  2. log.Printf("products count -> %d", len(products)) // 给我返回了 0 <---

应该改为:

  1. products, err := d.scrapperService.LoadProducts(702, 1, token)
  2. if err != nil {
  3. panic(err) // 实际上不要恐慌,但要找出出了什么问题
  4. }
  5. log.Printf("products count -> %d", len(products)) // 给我返回了 0 <---
英文:

Almost certainly you are returning an error, but then ignoring it.

> A nil slice has a length and capacity of 0 and has no underlying array. https://tour.golang.org/moretypes/12

You return nil, err here:

  1. // in LoadProducts
  2. if err != nil {
  3. return nil, err
  4. }

but then do

  1. products, _ := d.scrapperService.LoadProducts(702, 1, token)
  2. log.Printf(&quot;products count -&gt; %d&quot;, len(products)) // gives me 0 &lt;---

which should be

  1. products, err := d.scrapperService.LoadProducts(702, 1, token)
  2. if err != nil {
  3. panic(err) // dont actually panic, but figure out what went wrong
  4. }
  5. log.Printf(&quot;products count -&gt; %d&quot;, len(products)) // gives me 0 &lt;---

huangapple
  • 本文由 发表于 2021年10月9日 04:25:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/69501373.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定