sync.WaitGroup
Ожидание завершения группы горутин
«sync.WaitGroup» — бесплатный урок Go Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.
Назначение
sync.WaitGroup ожидает завершения группы горутин. Основная горутина вызывает Add, чтобы задать счётчик, каждая горутина вызывает Done после завершения, а Wait блокирует выполнение, пока счётчик не достигнет нуля.
Базовое использование
Вызывайте Add перед запуском каждой горутины, Done в конце каждой горутины (через defer), а Wait после запуска всех горутин.
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(v Item) {
defer wg.Done()
process(v)
}(item)
}
wg.Wait()Add должен выполняться до запуска горутины
Вызовите wg.Add(1) перед go func(), а не внутри горутины. Иначе Wait может завершиться до того, как горутина зарегистрирует себя.
Распространённая ошибка: захват переменной цикла
Передавайте переменную цикла как аргумент функции горутины, а не через замыкание, чтобы все горутины не использовали одну и ту же переменную.
for _, v := range items {
wg.Add(1)
go func(item Item) { // correct: copy
defer wg.Done()
process(item)
}(v)
}Повторное использование WaitGroup
WaitGroup можно повторно использовать после возврата из Wait, но только если все предыдущие вызовы Done завершились. Не используйте его повторно одновременно с незавершёнными вызовами Done.
WaitGroup и результаты
WaitGroup не собирает результаты — объедините его с каналом или срезом (с мьютексом), чтобы собрать вывод горутин.
results := make([]Result, len(items))
for i, item := range items {
wg.Add(1)
go func(idx int, v Item) {
defer wg.Done()
results[idx] = process(v)
}(i, item)
}
wg.Wait()Add с общим количеством
Можно передать общее количество в одном вызове Add перед циклом — это немного эффективнее, чем один Add для каждой горутины.
wg.Add(len(items))
for _, item := range items {
go func(v Item) { defer wg.Done(); process(v) }(item)
}Не копируйте WaitGroup
Как и мьютекс, WaitGroup нельзя копировать после первого использования. Передавайте его по указателю или встраивайте в структуру, передаваемую по указателю.
WaitGroup и errgroup
golang.org/x/sync/errgroup оборачивает WaitGroup и добавляет передачу ошибок. Предпочитайте errgroup, если сбой любой горутины должен остановить остальные.
Объединение с контекстом
Используйте errgroup.WithContext, чтобы получить и семантику WaitGroup, и контекст, который отменяется при первой ошибке и корректно останавливает все горутины.
g, ctx := errgroup.WithContext(context.Background())
g.Go(func() error { return doWork(ctx) })
if err := g.Wait(); err != nil { log.Fatal(err) }Нулевое значение можно использовать
Нулевое значение sync.WaitGroup готово к использованию — конструктор не нужен. Просто объявите его и вызовите Add.
Быстрая проверка
Что произойдёт, если вызвать wg.Add(1) внутри горутины, а не перед её запуском?
Повторение: sync.WaitGroup
Основные моменты:
- Add перед запуском горутины; Done через defer внутри горутины
- Wait блокирует выполнение, пока счётчик не достигнет нуля
- Никогда не копируйте WaitGroup и не вызывайте Add внутри горутины
- Используйте errgroup для передачи ошибок
Часто задаваемые вопросы
Урок «sync.WaitGroup» бесплатный?
Да — полный текст урока «sync.WaitGroup» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.
Чему я научусь в уроке «sync.WaitGroup»?
Ожидание завершения группы горутин Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Go Academy?
Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «sync.WaitGroup»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Go Academy?
Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.