Sobes.tech
Back to questions
Senior
2

```go func main() { wg := sync.WaitGroup{} for i := 0; i < 10; i++ { wg.Add(1) go func(wg sync.WaitGroup) { defer wg.Done() fmt.Println(i) }(wg) } wg.Wait() fmt.Println("some text") time.Sleep(1 * time.Minute) fmt.Println("some text2") } ```

Companies where asked
Базис

Answer from AI

sobes.tech AI

В данном коде есть несколько ошибок, связанных с использованием sync.WaitGroup и замыканиями в горутинах.

  1. Передача WaitGroup по значению: В функцию горутины func(wg sync.WaitGroup) WaitGroup передается по значению, то есть копируется. В результате вызов wg.Done() внутри горутины уменьшает счетчик копии, а не оригинального объекта, что приводит к тому, что wg.Wait() в main никогда не разблокируется.

    Правильный способ — передавать указатель на WaitGroup: func(wg *sync.WaitGroup) и вызывать wg.Done().

  2. Проблема с переменной i в замыкании: Переменная i используется внутри горутины, но она изменяется в цикле. Из-за этого все горутины могут вывести одно и то же значение (обычно 10).

    Чтобы исправить, нужно передавать i как параметр в анонимную функцию:

for i := 0; i < 10; i++ {
    wg.Add(1)
    go func(wg *sync.WaitGroup, val int) {
        defer wg.Done()
        fmt.Println(val)
    }(&wg, i)
}
  1. Итог исправленного кода:
package main

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

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(wg *sync.WaitGroup, val int) {
            defer wg.Done()
            fmt.Println(val)
        }(&wg, i)
    }

    wg.Wait()
    fmt.Println("some text")
    time.Sleep(1 * time.Minute)
    fmt.Println("some text2")
}

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