Sobes.tech
Назад к вопросам
Middle+
4

// У нас есть метод получения информации о товарах, данный метод вызывается очень часто // есть ли проблемы в этом коде и как исправить? база данных postgress func (r *ProductRepository) GetProductDetails(ctx context.Context, productIDs []int) []Product { products := make([]Product, 0, len(productIDs)) for _, id := range productIDs { go func(id int) { var p Product query := "SELECT name, price, description FROM products WHERE id = $1" err := r.db.QueryRowContext(ctx, query, id).Scan(&p.Name, &p.Price, &p.Desc) if err != nil { r.logger.Error("error get product", "err", err) return } products = append(products, p) }(id) } return products }

Компании, где спрашивали
Lenta Tech

Ответ от нейросети

sobes.tech AI

В представленном коде есть несколько проблем:

  1. Параллельное добавление в срез products без синхронизации — это приведёт к гонкам данных и потенциальному повреждению среза.
  2. Запуск горутин для каждого ID без контроля количества одновременно работающих горутин может привести к чрезмерной нагрузке на базу данных.
  3. Метод возвращает срез сразу, не дожидаясь завершения горутин, поэтому результат всегда будет пустым.

Как исправить:

  • Использовать один SQL-запрос с оператором IN для получения всех продуктов за один вызов, что эффективнее и проще.
  • Если нужно параллельно, использовать sync.WaitGroup и мьютекс для безопасного добавления в срез.

Пример исправленного варианта с одним запросом:

func (r *ProductRepository) GetProductDetails(ctx context.Context, productIDs []int) ([]Product, error) {
    query := `SELECT id, name, price, description FROM products WHERE id = ANY($1)`
    rows, err := r.db.QueryContext(ctx, query, pq.Array(productIDs))
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    var products []Product
    for rows.Next() {
        var p Product
        if err := rows.Scan(&p.ID, &p.Name, &p.Price, &p.Desc); err != nil {
            return nil, err
        }
        products = append(products, p)
    }
    return products, nil
}

Такой подход уменьшит нагрузку на базу и устранит проблемы с конкурентным доступом.