SoFunction
Updated on 2025-03-05

A article will help you learn about WaitGroups in Golang

What is WaitGroups

WaitGroupsIt is an effective way to synchronize your goroutines. Imagine you traveling with your family by car. Your dad stopped in a bar mall or fast food restaurant to buy some food and use the toilet. You'd better want to wait until everyone comes back before driving to the horizon.WaitGroupsHelp you do this.

WaitGroupsIt is by calling the standard librarysyncpackage defined.

var wg 

So, what isWaitGroupWoolen cloth?WaitGroupIt is a structure that contains how many programs need to wait forgoroutinesome information. It's a containing what you need to waitgoroutinesNumber of groups.

There are three most important methods for WaitGroups:AddDoneandWait

  • Add: Add to the total amount of goroutines you need to wait for.
  • Done: Subtract one from the total number of goroutines you need to wait for.
  • Wait: Block the code from continuing until there are no more goroutines to wait.

How to use WaitGroups

Let's take a look at a piece of code:

package main

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

func main() {
    var wg 
    (1)

    go func() {
        defer ()

        ((), "start")
        ()
        ((), "done")
    }()

    ()
    ((), "exiting...")
}

2022-08-21 17:01:54.184744229 +0900 KST m=+0.000021800 start
2022-08-21 17:01:55.184932851 +0900 KST m=+1.000210473 done
2022-08-21 17:01:55.18507731 +0900 KST m=+1.000354912 exiting...

  • We first initialize aWaitGroup wgExamples of .
  • Then we're inwgAdd 1 in it because we are waiting for onegoroutineFinish.
  • Then we run thisgoroutine. existgoroutineInside, we()Make a delayed call to ensure we decrement what we want to wait forgoroutinenumber. If we don't, the code will wait forevergoroutineCompleted and will result in a deadlock.
  • existgoroutineAfter the call, we want to make sure that the code is blocked untilWaitGroupis empty. We call()To do this.

Why use WaitGroups instead of channel

Now that we know how to use WaitGroups, a natural idea leads us to this question: Why use WaitGroups instead of channels?

In my experience, there are several reasons.

  • WaitGroupsIt's often more intuitive. When you read a piece of code, when you see aWaitGroupWhen you know what the code is doing immediately. The method has a clear name and goes straight to the topic. However, for the channel, it is sometimes not so clear. Using channels is smart, but it can be troublesome to understand when you read a complicated piece of code.
  • Sometimes, you don't need to use the channel. For example, let's look at this code:
 var wg 

  for i := 0; i < 5; i++ {
      (1)
      go func() {
          defer ()

          ((), "start")
          ()
          ((), "done")
      }()
  }

  ()
  ((), "exiting...")

You can see, thisgoroutineNot with othergoroutineConduct data exchange. If yoursgoroutineIt's a one-time job, you don't need to know the result, useWaitGroupIt is desirable. Now look at this code:

  ch := make(chan int)

  for i := 0; i < 5; i++ {
      go func() {
          randomInt := (10)
          ch <- randomInt
      }()
  }

  for i := 0; i < 5; i++ {
      (<-ch)
  }

here,goroutineIntochannelSend data. In these cases we do not need to useWaitGroup, because this will be redundant. If the reception has already blocked enough, why waitgoroutineFinish?

WaitGroupsIt is specially used to handle waitinggoroutinesof. I think the main purpose of the channel is to exchange data. You can't use itWaitGroupto send and receive data, but you can use onechannelLet's sync yourgoroutines

Finally, there is no correct answer. I know this may be annoying, but it depends on you and the team you work for. No matter what method is, it is wrong to have no answer. I personally prefer to useWaitGroupsDo the sync, but your situation may be different. Choose what is most intuitive for you.

One thing to note

Sometimes, you may need toWaitGroupPassing instance togoroutine. There may be severalWaitGroupTo handle differentgoroutine, may also be a design choice. Whatever the reason, make sure to pass the pointerWaitGrouppointer, like this:

var wg 

for i := 0; i < 5; i++ {
    (1)
    go func(wg *) {
        defer ()

        ((), "start")
        ()
        ((), "done")
    }(&wg)
}

()
((), "exiting...")

The reason is that Go is a language for passing values. This means that whenever you pass a parameter to a function, Go will copy a parameter and pass it to it instead of the original object. What happens in this case is that the wholeWaitGroupThe object will be copied, which meansgoroutineA completely different WaitGroup will be handled.()It will not be subtracted from the original wg, but a copy of it is subtracted, which only exists ingoroutinemiddle.

Summarize

By usingWaitGroups, we can easily synchronizegoroutines, thus ensuring that our code executes at the right time. Although channels can also be used for synchronization,WaitGroupsIt is usually more intuitive and easier to read. In useWaitGroupWhen you are in the process of passing the pointer correctly, make sure that the pointer is passed correctly.WaitGrouppointer to prevent copy problems. Whichever method you choose, you should choose the one that is most intuitive and best for you and your team.

This is the article about this article about WaitGroups in Golang. For more information about Golang WaitGroups, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!