Go

Пул воркеров на горутинах

Algonexys · 07.08.2026 · 👁 0

Обработка задач в несколько потоков с WaitGroup, каналами и отменой через context.

Код

package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

type Job struct {
	ID  int
	URL string
}

type Result struct {
	JobID int
	Value string
	Err   error
}

func worker(ctx context.Context, id int, jobs <-chan Job, results chan<- Result, wg *sync.WaitGroup) {
	defer wg.Done()
	for {
		select {
		case <-ctx.Done():
			return
		case job, ok := <-jobs:
			if !ok {
				return
			}
			time.Sleep(100 * time.Millisecond) // полезная работа
			results <- Result{JobID: job.ID, Value: fmt.Sprintf("worker %d: %s", id, job.URL)}
		}
	}
}

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	jobs := make(chan Job, 100)
	results := make(chan Result, 100)

	var wg sync.WaitGroup
	for i := 1; i <= 5; i++ {
		wg.Add(1)
		go worker(ctx, i, jobs, results, &wg)
	}

	go func() {
		for i := 1; i <= 20; i++ {
			jobs <- Job{ID: i, URL: fmt.Sprintf("https://example.com/%d", i)}
		}
		close(jobs)
	}()

	go func() {
		wg.Wait()
		close(results)
	}()

	for res := range results {
		if res.Err != nil {
			fmt.Printf("задача %d: ошибка %v\n", res.JobID, res.Err)
			continue
		}
		fmt.Println(res.Value)
	}
}