// В этом примере мы рассмотрим, как реализовать // _пул воркеров_ с использованием каналов и // горутин. package main import ( "fmt" "time" ) // Это воркер, который мы будем запускать в нескольких // параллельных инстансах. Эти воркеры будут получать // задания через канал `jobs` и отсылать результаты // в `results`. Мы будем ожидать одну секунду для // каждого задания для имитации тяжелого запроса. func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Println("worker", id, "started job", j) time.Sleep(time.Second) fmt.Println("worker", id, "finished job", j) results <- j * 2 } } func main() { // Чтобы использовать наш воркер пул, нам нужно // отправить им задание и получить результаты выполнения. // Для этого мы делаем 2 канала. jobs := make(chan int, 100) results := make(chan int, 100) // Стартуем 3 воркера, первоначально заблокированных, // т.к. еще нет заданий. for w := 1; w <= 3; w++ { go worker(w, jobs, results) } // Посылаем 5 `заданий (jobs)` и затем `закрываем` // канал, сообщая о том что все задания отправлены. for j := 1; j <= 5; j++ { jobs <- j } close(jobs) // Наконец мы собираем все результаты. Это также // гарантирует, что горутины закончились. Альтернативный // способ ожидания нескольких процедур заключается // в использовании [WaitGroup](waitgroups). for a := 1; a <= 5; a++ { <-results } }