```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") } ```
Ответ от нейросети
sobes.tech AI
В данном коде есть несколько ошибок, связанных с использованием sync.WaitGroup и замыканиями в горутинах.
-
Передача WaitGroup по значению: В функцию горутины
func(wg sync.WaitGroup)WaitGroup передается по значению, то есть копируется. В результате вызовwg.Done()внутри горутины уменьшает счетчик копии, а не оригинального объекта, что приводит к тому, чтоwg.Wait()в main никогда не разблокируется.Правильный способ — передавать указатель на WaitGroup:
func(wg *sync.WaitGroup)и вызыватьwg.Done(). -
Проблема с переменной 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)
}
- Итог исправленного кода:
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 и фиксировать значение переменной цикла для корректной работы горутин и синхронизации.