What is WaitGroups
WaitGroups
It 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.WaitGroups
Help you do this.
WaitGroups
It is by calling the standard librarysync
package defined.
var wg
So, what isWaitGroup
Woolen cloth?WaitGroup
It is a structure that contains how many programs need to wait forgoroutine
some information. It's a containing what you need to waitgoroutines
Number of groups.
There are three most important methods for WaitGroups:Add
, Done
andWait
。
- 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 a
WaitGroup wg
Examples of . - Then we're in
wg
Add 1 in it because we are waiting for onegoroutine
Finish. - Then we run this
goroutine
. existgoroutine
Inside, we()
Make a delayed call to ensure we decrement what we want to wait forgoroutine
number. If we don't, the code will wait forevergoroutine
Completed and will result in a deadlock. - exist
goroutine
After the call, we want to make sure that the code is blocked untilWaitGroup
is 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.
-
WaitGroups
It's often more intuitive. When you read a piece of code, when you see aWaitGroup
When 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, thisgoroutine
Not with othergoroutine
Conduct data exchange. If yoursgoroutine
It's a one-time job, you don't need to know the result, useWaitGroup
It 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,goroutine
Intochannel
Send data. In these cases we do not need to useWaitGroup
, because this will be redundant. If the reception has already blocked enough, why waitgoroutine
Finish?
WaitGroups
It is specially used to handle waitinggoroutines
of. I think the main purpose of the channel is to exchange data. You can't use itWaitGroup
to send and receive data, but you can use onechannel
Let'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 useWaitGroups
Do the sync, but your situation may be different. Choose what is most intuitive for you.
One thing to note
Sometimes, you may need toWaitGroup
Passing instance togoroutine
. There may be severalWaitGroup
To handle differentgoroutine
, may also be a design choice. Whatever the reason, make sure to pass the pointerWaitGroup
pointer, 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 wholeWaitGroup
The object will be copied, which meansgoroutine
A 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 ingoroutine
middle.
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,WaitGroups
It is usually more intuitive and easier to read. In useWaitGroup
When you are in the process of passing the pointer correctly, make sure that the pointer is passed correctly.WaitGroup
pointer 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!