Search code examples
mongodbgogoroutinemgo

How to make sure goroutine fully runs before exiting


I have a function calling a go routine that calls additional functions within it. However, those go routines are exiting before being completely finished. How would I make sure all the underlying code within the function (migrateUserHelper) runs before the exit. Here is my code below:

func MigrateUsers(){
  var wg sync.WaitGroup
  userCount:=10 //userDAO.GetUserCount()
  limitSize:=2
  count:=0
  divisor = userCount/limitSize
  for divisor>0{
      wg.Add(1)
      go migrateUserHelper(limitSize,&wg,count)
      divisor =divisor -1
      count=count +1
  }
  wg.Wait()
  fm.Println("DONE BATCHES")
 }
 func migrateUserHelper(limitSize int, count int, wg *sync.WaitGroup) 
 {
   defer wg.Done()
   fmt.Println("Start batch "+strconv.Itoa(count))
   users:= userDAO.GetUsers(limitSize)
   fmt.Println("Fetched Users for batch "+ strconv.Itoa(count))
   userDAO.BulkUpdateUsers(users)
  fmt.Println("Reconciled Users for batch "+ strconv.Itoa(count))
}

Im trying to update A LOT OF records in the database simultaneously in different go routines.

Thanks


Solution

  • The WaitGroup is a counting semaphore and can be used to count off goroutines as they finish their work, but for that, you need to set how many goroutines you are going to spawn. You can do that by calling the method Add:

    package main
    
    import (
        "fmt"
        "strconv"
        "sync"
    )
    
    func main() {
        migrateUsers()
    }
    
    func migrateUsers() {
        var wg sync.WaitGroup
    
        userCount := 10
        limitSize := 2
        count := 0
        divisor := userCount / limitSize
        wg.Add(divisor)
    
        for divisor > 0 {
            go migrateUserHelper(limitSize, count, &wg)
            divisor = divisor - 1
            count = count + 1
        }
    
        wg.Wait()
        fmt.Println("DONE BATCHES")
    }
    
    func migrateUserHelper(limitSize int, count int, wg *sync.WaitGroup) {
        defer wg.Done()
        fmt.Println("Start batch " + strconv.Itoa(count))
        fmt.Println("Fetched Users for batch " + strconv.Itoa(count))
        fmt.Println("Reconciled Users for batch " + strconv.Itoa(count))
    }
    

    playground.