Метод sync.WaitGroup.Done

Метод sync.WaitGroup.Done уменьшает внутренний счетчик структуры WaitGroup на единицу. Он вызывается внутри горутины для того, чтобы сообщить, что она завершила свою работу. Как правило, метод вызывается с помощью ключевого слова defer, чтобы гарантировать уменьшение счетчика даже в случае паники. Метод не принимает никаких параметров и не возвращает значений.

Синтаксис

gowg.Done()

Пример

Давайте создадим группу ожидания, запустим две горутины и уменьшим счетчик с помощью Done после завершения каждой из них:

gopackage main

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

func main() {
  var wg sync.WaitGroup

  wg.Add(2)

  go func() {
    defer wg.Done()
    time.Sleep(100 * time.Millisecond)
    fmt.Println("goroutine 1 done")
  }()

  go func() {
    defer wg.Done()
    time.Sleep(50 * time.Millisecond)
    fmt.Println("goroutine 2 done")
  }()

  wg.Wait()
  fmt.Println("all goroutines done")
}

Результат выполнения кода:

go"goroutine 2 done"
"goroutine 1 done"
"all goroutines done"

Пример

Если горутина завершается с паникой, defer гарантирует, что Done все равно будет вызван. В этом примере счетчик будет уменьшен, несмотря на панику:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var wg sync.WaitGroup

  wg.Add(1)

  go func() {
    defer wg.Done()
    panic("something went wrong")
  }()

  wg.Wait()
  fmt.Println("wait finished")
}

Результат выполнения кода:

go"wait finished"

Пример

Метод Done можно вызвать явно без defer, но важно убедиться, что он будет выполнен в любом случае:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var wg sync.WaitGroup

  wg.Add(3)

  for i := 0; i < 3; i++ {
    go func(id int) {
      fmt.Printf("goroutine %d done\n", id)
      wg.Done()
    }(i)
  }

  wg.Wait()
  fmt.Println("all done")
}

Результат выполнения кода:

go"goroutine 2 done"
"goroutine 0 done"
"goroutine 1 done"
"all done"

Смотрите также

  • метод sync.WaitGroup.Add,
    который увеличивает счетчик ожидания
  • метод sync.WaitGroup.Wait,
    который блокирует выполнение до обнуления счетчика
  • саму структуру sync.WaitGroup,
    которая используется для ожидания завершения горутин
  • примитив синхронизации sync.Mutex,
    который защищает общие данные от конкурентного доступа