Установить максимум одновременно запущенных вызовов функции printNumber

Приведённый код уже ограничивает число одновременных printNumber тремя: вход в функцию возможен только после получения слота в канале.

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

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

Приведённый код уже ограничивает число одновременных printNumber тремя: вход в функцию возможен только после получения слота в канале.

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

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

Условие

Модифицируйте программу так, чтобы одновременно выполнялось не более трёх вызовов функции printNumber.

package main

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

func main() {
    var wg sync.WaitGroup
    sem := make(chan struct{}, 3) // семафор, ограничивающий количество одновременных вызовов

    for idx := 0; idx < 10; idx++ {
        wg.Add(1)
        go func(n int) {
            defer wg.Done()
            sem <- struct{}{}   // захватываем слот
            printNumber(n)
            <-sem               // освобождаем слот
        }(idx)
    }

    wg.Wait()
}

func printNumber(num int) {
    time.Sleep(time.Second)
    fmt.Println(num)
}

Ответ

Приведённый код уже ограничивает число одновременных printNumber тремя: вход в функцию возможен только после получения слота в канале.

Созданных горутин будет десять, но одновременно внутри printNumber — не больше трёх. Остальные ждут отправки в заполненный sem. WaitGroup корректно ждёт их завершения.

Небольшое улучшение: после sem <- struct{}{} выполнить defer func() { <-sem }(), чтобы освобождение слота не зависело от будущих ранних return. Если необходимо ограничить и количество живых горутин, слот захватывают перед go или используют фиксированный пул работников. Это другое ограничение, которого текущая задача не требует.

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

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

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

Подробнее