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

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

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

问题

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

func (d *dataBaseWriterImpl) WriteProducts() error {
	username := os.Getenv("USERNAME")
	password := os.Getenv("PASSWORD")

	// 获取令牌
	token, err := d.authService.Login(username, password)
	if err != nil {
		return err
	}

	// 加载产品
	// 这里的问题是如果数量超过700 <----
	products, _ := d.scrapperService.LoadProducts(702, 1, token)
	log.Printf("产品数量 -> %d", len(products)) // 返回的是0 <-----

	errChan := make(chan error, 2)
	var cats []models.Category
	db.Conn.Model(&models.Category{}).Find(&cats)
	var catIds []string
	for _, cat := range cats {
		catIds = append(catIds, cat.ExternalId)
	}

	for _, prod := range products {
		if d.isValidProduct(catIds, prod.PrimaryVariant.CategoryID) {
			log.Printf("更新ID -> %v", prod.PrimaryVariant.ID)
			go d.saveOrUpdateProducts(prod.PrimaryVariant, errChan)
		} else {
			log.Printf("不会更新ID -> %v", prod.PrimaryVariant.ID)
			go func() {
				errChan <- nil
			}()
		}

	}
	for range products {
		err := <-errChan
		if err != nil {
			return err
		}
	}
	return nil
}

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

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)

	// 创建请求
	req, err := http.NewRequest("POST", fmt.Sprintf("%v/api/variantGroups/search", os.Getenv("BACKEND")), body)
	if err != nil {
		log.Print(err)
	}
	// 请求头
	//req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:84.0) Gecko/20100101 Firefox/84.0")
	req.Header.Add("Accept", "application/json, text/plain, */*")
	req.Header.Add("Authorization", fmt.Sprintf("Bearer %v", token))
	req.Header.Add("Content-Type", "application/json")

	// 发送请求
	resp, err := s.client.Do(req)

	if err != nil {
		fmt.Println("失败: ", err)
	}

	//[]models.Product `json:"data"`
	// 读取响应
	type Response struct {
		Results []models.VariantsResult `json:"results"`
		Count   int                     `json:"count"`
	}
	var response Response

	err = json.NewDecoder(resp.Body).Decode(&response)
	log.Printf("产品 -> %d", len(response.Results)) // 返回的是实际数量 <--
	if err != nil {
		return nil, err
	}
	return response.Results, nil
}
英文:

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.

func (d *dataBaseWriterImpl) WriteProducts() error {
	username := os.Getenv(&quot;USERNAME&quot;)
	password := os.Getenv(&quot;PASSWORD&quot;)

	// get token
	token, err := d.authService.Login(username, password)
	if err != nil {
		return err
	}

	// load products
    // here the problem if count more than 700 &lt;----
	products, _ := d.scrapperService.LoadProducts(702, 1, token)
	log.Printf(&quot;products count -&gt; %d&quot;, len(products)) // gives me 0 &lt;-----

	errChan := make(chan error, 2)
	var cats []models.Category
	db.Conn.Model(&amp;models.Category{}).Find(&amp;cats)
	var catIds []string
	for _, cat := range cats {
		catIds = append(catIds, cat.ExternalId)
	}

	for _, prod := range products {
		if d.isValidProduct(catIds, prod.PrimaryVariant.CategoryID) {
			log.Printf(&quot;update id -&gt; %v&quot;, prod.PrimaryVariant.ID)
			go d.saveOrUpdateProducts(prod.PrimaryVariant, errChan)
		} else {
			log.Printf(&quot;will not update id -&gt; %v&quot;, prod.PrimaryVariant.ID)
			go func() {
				errChan &lt;- nil
			}()
		}

	}
	for range products {
		err := &lt;-errChan
		if err != nil {
			return err
		}
	}
	return nil
}

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

func (s serviceImpl) LoadProducts(count uint, page uint, token string) ([]models.VariantsResult, error) {

	jsonBody := []byte(fmt.Sprintf(`{&quot;pageSize&quot;: %d, &quot;page&quot;: %d, &quot;sortBy&quot;: &quot;updatedAt&quot;}`, count, page))
	body := bytes.NewBuffer(jsonBody)

	// Create request
	req, err := http.NewRequest(&quot;POST&quot;, fmt.Sprintf(&quot;%v/api/variantGroups/search&quot;, os.Getenv(&quot;BACKEND&quot;)), body)
	if err != nil {
		log.Print(err)
	}
	// Headers
	//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;)
	req.Header.Add(&quot;Accept&quot;, &quot;application/json, text/plain, */*&quot;)
	req.Header.Add(&quot;Authorization&quot;, fmt.Sprintf(&quot;Bearer %v&quot;, token))
	req.Header.Add(&quot;Content-Type&quot;, &quot;application/json&quot;)

	// Fetch Request
	resp, err := s.client.Do(req)

	if err != nil {
		fmt.Println(&quot;Failure : &quot;, err)
	}

	//[]models.Product `json:&quot;data&quot;`
	// Read Response
	type Response struct {
		Results []models.VariantsResult `json:&quot;results&quot;`
		Count   int                     `json:&quot;count&quot;`
	}
	var response Response

	err = json.NewDecoder(resp.Body).Decode(&amp;response)
	log.Printf(&quot;products -&gt; %d&quot;, len(response.Results)) // gives me actual number &lt;--
	if err != nil {
		return nil, err
	}
	return response.Results, nil
}

答案1

得分: 3

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

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

你在这里返回了 nil, err:

// 在 LoadProducts 中
if err != nil {
    return nil, err
}

但是接下来却这样做了:

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

应该改为:

products, err := d.scrapperService.LoadProducts(702, 1, token)
if err != nil {
    panic(err) // 实际上不要恐慌,但要找出出了什么问题
}
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:

// in LoadProducts
if err != nil {
    return nil, err
}

but then do

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

which should be

products, err := d.scrapperService.LoadProducts(702, 1, token)
if err != nil {
    panic(err) // dont actually panic, but figure out what went wrong
}
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:

确定