// GetUsersList возвращает список пользователей. (в бд храним порядка 1 млн пользователей)

Код не компилируется и имеет N+1-запросы, утечки rows и неверную фильтрацию isActive=false. Для миллиона записей обязательны пагинация и отделение внешнего API.

Короткий ответ

Что ответить на собеседовании

Код не компилируется и имеет N+1-запросы, утечки rows и неверную фильтрацию isActive=false. Для миллиона записей обязательны пагинация и отделение внешнего API.

Подробный разбор

Ответ с пояснениями

Условие

// GetUsersList возвращает список пользователей. (в бд храним порядка 1 млн пользователей) // Используется для отображения списка пользователей в админке. Если isActive = true, то возвращаются только активные пользователи. func (u *UsersRepo) GetUsersList(ctx context.Context, isActive bool) ([]User, error) { rows, err := u.DB.Query("SELECT id, name, phone FROM users WHERE is_active = ?", isActive) if err != nil { return nil, errors.New("ошибка получения списка пользователей") } var users []User // Заполним информацию о пользователях. for rows.Next() { var user User err := rows.Scan(&user.ID, &user.Name, &user.Phone) if err != nil { return nil, err } // Получим список e-mail пользователя err, err := u.DB.QueryContext(ctx, "SELECT email FROM user_emails WHERE user_id = ?", user.ID) if err != nil { return nil, errors.New("ошибка получения списка пользователей") } var emails []string for er.Next() { var email string err := rows.Scan(&email) if err != nil { return nil, err } emails = append(emails, email) } if len(emails) != 0 { for i, e := range emails { emails[i] = strings.ToLower(e) } } user.Emails = emails // Получим информацию о профиле из апи ВКонтакте profile, err := getUserProfileFromVkApiByUserPhone(user.Phone) if err != nil { return nil, errors.New("ошибка получения списка пользователей") } user.Profile = profile users = append(users, user) } if err = rows.Err(); err != nil { return nil, errors.New("ошибка получения списка пользователей") } }

Ответ

Код не компилируется и имеет N+1-запросы, утечки rows и неверную фильтрацию isActive=false. Для миллиона записей обязательны пагинация и отделение внешнего API.

Сначала исправьте ошибки: err, err := должно объявлять отдельный er, сканировать email нужно через er.Scan, в конце отсутствует return users, nil. Используйте QueryContext, закрывайте оба набора rows и проверяйте их Err.

По условию false означает «все», а текущий WHERE возвращает только неактивных. Стройте фильтр только при true. Добавьте ограниченный размер страницы и стабильный порядок по id; email загружайте одним пакетным запросом для этой страницы, после закрытия основного rows.

Вызовы VK вынесите из репозитория в отдельное обогащение с таймаутами, кэшем и ограниченной конкурентностью. Не прячьте причины ошибок за одинаковой строкой; сохраняйте контекст через wrapping. Полное исправление требует изменения контракта метода для пагинации, а не одной замены строки.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее