Продолжаем работать с функциями-говорилками. На предыдущем шаге мы заставили их обрабатывать исходные данные в две горутины, с помощью пула:
func main() {
phrases := []string{
// ...
}
// пул идентификаторов для 2 горутин
pool := make(chan int, 2)
pool <- 1
pool <- 2
for _, phrase := range phrases {
// получаем идентификатор из пула,
// если есть свободные
id := <-pool
go say(pool, id, phrase)
}
// дожидаемся, пока все горутины закончат работу
// (то есть все идентификаторы вернутся в пул)
<-pool
<-pool
}
func say(pool chan<- int, id int, phrase string) {
for _, word := range strings.Fields(phrase) {
// ...
}
// возвращаем идентификатор в пул
pool <- id
}
Это работает, но как-то... кривовато. Во-первых, получился пул строго на две горутины (а вдруг понадобится десять?). Во-вторых, логика пула размазана по всей программе — это чревато ошибками.
Хочется, чтобы функция say()
ничего не знала о пуле:
func say(id int, phrase string) {
for _, word := range strings.Fields(phrase) {
// ...
}
}
А функция main()
чтобы выглядела так:
func main() {
phrases := []string{
// ...
}
handle, wait := makePool(2, say)
for _, phrase := range phrases {
handle(phrase)
}
wait()
}
Конструктор makePool()
создает пул на указанное количество обработчиков. Он также принимает функцию-обработчик, которую будет вызывать позже. Конструктор возвращает две функции:
handle()
выбирает токен из пула и обрабатывает переданную фразу через функцию-обработчик;wait()
дожидается, пока все токены вернутся в пул;
Вот шаблон makePool()
:
func makePool(n int, handler func(int, string)) (func(string), func()) {
// создайте пул на n обработчиков
// используйте имя pool для канала
// определите функции handle() и wait()
// handle() выбирает токен из пула
// и обрабатывает переданную фразу через handler()
// wait() дожидается, пока все токены вернутся в пул
return handle, wait
}
Реализуйте внутренности.
Полный код — в песочнице. Отправляйте в качестве решения только фрагмент, отмеченный комментариями «начало решения» и «конец решения».
Sample Input:
Sample Output:
PASS