Напишите программу, которая:

Неизвестное число URL удобно передавать каналом: источник закрывает его по окончании, работники завершаются, а координатор закрывает результаты после WaitGroup.

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

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

Неизвестное число URL удобно передавать каналом: источник закрывает его по окончании, работники завершаются, а координатор закрывает результаты после WaitGroup.

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

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

Условие

Напишите программу, которая:

  1. Поочередно выполнит http запросы по предложенному списку ссылок • в случае получения http-кода ответа на запрос "200 OK" печатаем на экране "адрес url - ok" • в случае получения http-кода ответа на запрос отличного от "200 OK" либо в случае ошибки печатаем на экране "адрес url - not ok"

  2. Модифицируйте программу таким образом, чтобы использовались каналы для коммуникации основного потока с горутинами. Пример: Запросы по списку выполняются в горутинах. Печать результатов на экран происходит в основном потоке.

  3. Модифицируйте программу таким образом, чтобы нигде не использовалась длина слайса урлов. Считайте, что урлы приходят из внешнего источника. Сколько их будет заранее - неизвестно. Предложите идиоматичный вариант, как ваша программа будет узнавать об окончании списка и передавать сигнал об окончании действий далее.

Ответ

Неизвестное число URL удобно передавать каналом: источник закрывает его по окончании, работники завершаются, а координатор закрывает результаты после WaitGroup.

Ниже Go-программа без использования len(urls). При workers=1 запросы последовательны; большее число включает ограниченный параллелизм. Печатает основная горутина.

package main

import (
    "fmt"
    "net/http"
    "sync"
    "time"
)

type Result struct { URL string; OK bool }

func check(client *http.Client, url string) Result {
    resp, err := client.Get(url)
    if err != nil { return Result{URL: url} }
    defer resp.Body.Close()
    return Result{URL: url, OK: resp.StatusCode == http.StatusOK}
}

func run(urls <-chan string, workers int) {
    if workers < 1 { panic("workers must be positive") }
    client := &http.Client{Timeout: 5 * time.Second}
    out := make(chan Result)
    var wg sync.WaitGroup
    for i := 0; i < workers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for url := range urls { out <- check(client, url) }
        }()
    }
    go func() { wg.Wait(); close(out) }()
    for r := range out {
        status := "not ok"
        if r.OK { status = "ok" }
        fmt.Printf("%s - %s\n", r.URL, status)
    }
}

func main() {
    urls := make(chan string)
    go func() {
        defer close(urls)
        // Здесь может находиться чтение внешнего источника до EOF.
        for _, url := range []string{"https://example.com", "https://example.org"} {
            urls <- url
        }
    }()
    run(urls, 3)
}

Вывод при параллельной работе идёт по готовности. Источник обязан закрыть канал после завершения; для прекращения незавершённого внешнего источника дополнительно нужен общий context.

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

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

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

Подробнее