Дана функция lookupID, которая ходит в сеть и по имени возвращает ID. Её и
main менять нельзя. Нужно реализовать Collect: вызвать lookupID для
каждого человека параллельно и собрать map[имя]ID.
type Person struct {
Name string
}
// lookupID не трогаем (в решении уже объявлена)
var lookupID = func(ctx context.Context, name string) (int, error) {
time.Sleep(15 * time.Millisecond)
return rand.Int() % 100000, nil
}
// менять можно только эту функцию
func Collect(ctx context.Context, people []Person) (map[string]int, error)
func main() {
fmt.Println(Collect(context.Background(), []Person{{"aaa"}, {"bbb"}, {"ccc"}, {"ddd"}, {"eeee"}}))
}
Требования
- Все вызовы
lookupID идут одновременно: Collect для N людей занимает
примерно один вызов (~15 мс), а не N.
lookupID получает ctx, переданный в Collect.
- Одно и то же имя может встретиться несколько раз.
lookupID для него
вызывается один раз.
- Ошибка одного вызова не прерывает остальные. В map попадают все успешные
имена. Ошибка результата — все ошибки через
errors.Join, каждая с именем
(errors.Is находит исходную). Если ошибок нет, возвращается nil.
- Пустой список → пустая (не
nil) map и nil.
- После возврата горутин не остаётся. Код проходит
go test -race.
Пример
m, err := Collect(ctx, []Person{{"aaa"}, {"bbb"}, {"aaa"}})
// ≈ 15 мс; m = map[aaa:4211 bbb:87] (ID случайные), err = nil; lookupID вызван 2 раза
Устно: мьютекс или канал — что выберешь для сбора результата и почему?
Что изменится, если людей 100 000?
Разбор и эталонное решение — после своей попытки: на собеседовании подсказок не будет.
Сначала попробуй сам — подсказки не дают готовый ответ.