Sobes.tech
Junior — Senior
62

Ускорение выполнения через параллельные запросы

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

Mail.ruMail.ru
Условие задачи

Необходимо доработать функцию Do так, чтобы её выполнение занимало около 10 мс независимо от количества переданных пользователей. Каждый вызов fetchByName имитирует задержку в 10 мс. Функции main и fetchByName менять нельзя – вся оптимизация должна быть реализована внутри Do.

package main

import (
    "context"
    "fmt"
    "math/rand"
    "sync"
    "time"
)

type User struct {
    Name string
}

func main() {
    fmt.Println(Do(context.Background(), []User{{"aaa"}, {"bbb"}, {"ccc"}, {"ddd"}, {"eeee"}}))
}

// fetchByName изменять нельзя
func fetchByName(ctx context.Context, userName string) (int, error) {
    time.Sleep(10 * time.Millisecond) // имитация сетевого похода
    return rand.Int() % 100000, nil
}

// все изменения должны происходить в этой функции
func Do(ctx context.Context, users []User) (map[string]int, error) {
    result := make(map[string]int)
    var mu sync.Mutex
    var wg sync.WaitGroup
    errCh := make(chan error, 1)

    for _, usr := range users {
        wg.Add(1)
        go func(u User) {
            defer wg.Done()
            id, err := fetchByName(ctx, u.Name)
            if err != nil {
                select {
                case errCh <- err:
                default:
                }
                return
            }
            mu.Lock()
            result[u.Name] = id
            mu.Unlock()
        }(usr)
    }

    wg.Wait()
    close(errCh)

    if err, ok := <-errCh; ok {
        return result, err
    }
    return result, nil
}