Вместо горутины на каждый URL создайте фиксированный пул работников. Уберите log.Fatal из работника: он завершает весь процесс, а не только обработку неудачного запроса.
Оптимизация массовых HTTP-запросов
Вместо горутины на каждый URL создайте фиксированный пул работников. Уберите log.Fatal из работника: он завершает весь процесс, а не только обработку неудачного запроса.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Нужно адаптировать реализацию параллельных HTTP-запросов к большому числу URL-адресов, чтобы избежать чрезмерного потребления ресурсов. Требуется ограничить количество одновременно выполняемых запросов
func printCodes(urls []string) {
var wg sync.WaitGroup
wg.Add(len(urls))
get := func(url string) {
resp, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
fmt.Println(url, resp.Status)
defer wg.Done()
}
for _, url := range urls {
url := url
go get(url)
}
wg.Wait()
}
Ответ
Вместо горутины на каждый URL создайте фиксированный пул работников. Уберите log.Fatal из работника: он завершает весь процесс, а не только обработку неудачного запроса.
Вариант с четырьмя работниками; нужны fmt, log, net/http, sync, time:
func printCodes(urls []string) {
jobs := make(chan string)
client := &http.Client{Timeout: 5*time.Second}
var wg sync.WaitGroup
for i := 0; i < 4; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for url := range jobs {
resp, err := client.Get(url)
if err != nil { log.Printf("%s: %v", url, err); continue }
fmt.Println(url, resp.Status)
resp.Body.Close()
}
}()
}
for _, url := range urls { jobs <- url }
close(jobs)
wg.Wait()
}
Тело не сохраняется, потому что задача требует лишь HTTP-статусы. Для раннего прекращения добавьте context и отменяемую отправку заданий. Количество горутин и одновременных запросов не растёт вместе с длиной списка.