英文:
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("USERNAME")
password := os.Getenv("PASSWORD")
// get token
token, err := d.authService.Login(username, password)
if err != nil {
return err
}
// load products
// here the problem if count more than 700 <----
products, _ := d.scrapperService.LoadProducts(702, 1, token)
log.Printf("products count -> %d", len(products)) // gives me 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("update id -> %v", prod.PrimaryVariant.ID)
go d.saveOrUpdateProducts(prod.PrimaryVariant, errChan)
} else {
log.Printf("will not update id -> %v", prod.PrimaryVariant.ID)
go func() {
errChan <- nil
}()
}
}
for range products {
err := <-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(`{"pageSize": %d, "page": %d, "sortBy": "updatedAt"}`, count, page))
body := bytes.NewBuffer(jsonBody)
// Create request
req, err := http.NewRequest("POST", fmt.Sprintf("%v/api/variantGroups/search", os.Getenv("BACKEND")), body)
if err != nil {
log.Print(err)
}
// Headers
//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")
// Fetch Request
resp, err := s.client.Do(req)
if err != nil {
fmt.Println("Failure : ", err)
}
//[]models.Product `json:"data"`
// Read Response
type Response struct {
Results []models.VariantsResult `json:"results"`
Count int `json:"count"`
}
var response Response
err = json.NewDecoder(resp.Body).Decode(&response)
log.Printf("products -> %d", len(response.Results)) // gives me actual number <--
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("products count -> %d", len(products)) // gives me 0 <---
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("products count -> %d", len(products)) // gives me 0 <---
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论