Для Go 1.21 передайте idx аргументом горутины и дождитесь всех через WaitGroup. Исходник не гарантирует ни полный вывод, ни правильный захват индексов.
Коррекция замыкания и взаимодействие с планировщиком
Для Go 1.21 передайте idx аргументом горутины и дождитесь всех через WaitGroup. Исходник не гарантирует ни полный вывод, ни правильный захват индексов.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо поправить программу, чтобы она надёжно выводила числа от 0 до 9. После исправления следует объяснить, как внутри планировщика Go происходит распределение работы. Какие результаты выдаст приведённый фрагмент при запуске на Go 1.21? Как гарантировать, что на экран появятся все числа от 0 до 9? Охарактеризуйте, каким образом планировщик распределяет горутины и почему это связано с тем, как захватывается переменная цикла.
func main() {
for idx := 0; idx < 10; idx++ {
go func() {
fmt.Println(idx)
}()
}
}
Ответ
Для Go 1.21 передайте idx аргументом горутины и дождитесь всех через WaitGroup. Исходник не гарантирует ни полный вывод, ни правильный захват индексов.
Исправление:
func main() {
var wg sync.WaitGroup
for idx := 0; idx < 10; idx++ {
wg.Add(1)
go func(idx int) {
defer wg.Done()
fmt.Println(idx)
}(idx)
}
wg.Wait()
}
Нужны fmt и sync. Печатаются все числа 0–9, но не обязательно по порядку. Планировщик распределяет горутины G по потокам M через ресурсы P; GOMAXPROCS ограничивает одновременное выполнение Go-кода. Захват общей переменной определяется семантикой языка, а планирование лишь делает гонку наблюдаемой. В Go 1.21 без локальной копии цикл переиспользует idx.