Назад к задачам
Вкусвилл АвтомаконПолучайте помощь с лайвкодингом в реальном времени с Sobes Copilot
Junior — Senior
5
Проблема гонки данных при запуске горутин в цикле
Компании, где спрашивали:
Условие задачи
В этом примере показана типичная ошибка, когда несколько горутин одновременно используют переменную цикла. Какой именно баг присутствует в коде и какие способы позволяют избавиться от него?
func main(){
for i := 0; i < 10: i++ {
go func(){
fmt.Println(i)
}()
}
}
Что происходит:
- Цикл использует одну и ту же переменную
iдля всех итераций. К моменту выполнения анонимной функции значениеiуже может измениться, поэтому горутины могут вывести одинаковые или «пропущенные» числа. - Кроме того, в заголовке цикла стоит двоеточие вместо точки с запятой, что делает код синтаксически неверным.
Как исправить:
- Передать текущий индекс в функцию как параметр. Это создаст отдельную копию значения для каждой горутины.
func main() {
for idx := 0; idx < 10; idx++ {
go func(v int) {
fmt.Println(v)
}(idx)
}
}
- Локальная переменная внутри тела цикла.
func main() {
for i := 0; i < 10; i++ {
v := i // отдельная копия
go func() {
fmt.Println(v)
}()
}
}
- Синхронизация завершения горутин, например, через
sync.WaitGroup, чтобы гарантировать вывод всех чисел до завершения программы.
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(v int) {
defer wg.Done()
fmt.Println(v)
}(i)
}
wg.Wait()
}
Эти приёмы устраняют состояние гонки и делают программу предсказуемой.