Передавайте право печати по кольцу из трёх каналов. Каждая горутина печатает один элемент и передаёт сигнал следующей, поэтому получится 1–9 по порядку.
Организованный вывод чисел из нескольких горутин
Передавайте право печати по кольцу из трёх каналов. Каждая горутина печатает один элемент и передаёт сигнал следующей, поэтому получится 1–9 по порядку.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
В программе запускаются три горутины, каждая из которых печатает числа из собственного массива. Требуется изменить код так, чтобы числа выводились в строгом порядке, при этом вызов fmt.Println() должен оставаться внутри цикла каждой горутины.
package main
import (
"fmt"
"sync"
)
func main() {
var waitGroup sync.WaitGroup
waitGroup.Add(3)
go func() {
for _, v := range []int{1, 4, 7} {
fmt.Println(v)
}
waitGroup.Done()
}()
go func() {
for _, v := range []int{2, 5, 8} {
fmt.Println(v)
}
waitGroup.Done()
}()
go func() {
for _, v := range []int{3, 6, 9} {
fmt.Println(v)
}
waitGroup.Done()
}()
waitGroup.Wait()
}
Ответ
Передавайте право печати по кольцу из трёх каналов. Каждая горутина печатает один элемент и передаёт сигнал следующей, поэтому получится 1–9 по порядку.
Основная часть main с импортами fmt и sync:
turns := []chan struct{}{make(chan struct{}, 1), make(chan struct{}, 1), make(chan struct{}, 1)}
arrays := [][]int{{1,4,7}, {2,5,8}, {3,6,9}}
var wg sync.WaitGroup
for index, values := range arrays {
wg.Add(1)
go func(index int, values []int) {
defer wg.Done()
for _, value := range values {
<-turns[index]
fmt.Println(value)
turns[(index+1)%3] <- struct{}{}
}
}(index, values)
}
turns[0] <- struct{}{}
wg.Wait()
Буфер на один сигнал нужен и для последней передачи после 9, когда первый работник уже завершён. Код рассчитан на три одинаковые по длине последовательности из условия; для разных длин нужен иной протокол завершения.