This lesson is locked. Login or Subscribe for more access!

Working with errgroups

Duration: 6 mins

Learn how to use errgroups and why they are my favourite Go package.

Instructor

Matt Boyle

Share with a friend!

Transcript

In this video we're going to talk about the error group package and how it can dramatically improve the performance of your application when making multiple HTTP requests. We're going to start with a basic example and then gradually improve it to show you how powerful error groups are. Error groups are probably my favorite package. I use them all the time.

Let's write some basic code to make a bunch of HTTP requests. We start with sequential requests - each request waits for the previous one to complete even though they're not related to each other in any way whatsoever. There's no reason that we have to wait for the Facebook request to complete before we can make the Microsoft request, and also notice these are HTTP get calls they're not mutating anything back-end anywhere.

One thing we can do is make this asynchronous with a wait group. We can do sync.waitgroup and since we know we're going to make three requests, we do wg.add3. Then we wrap all of these in GoFuncs with defer wg.done and wg.wait at the bottom.

However, one problem with this approach is error handling - I haven't done a good job here. What we probably should have done is added a channel to handle the errors. Right now it's ignoring all the errors because crashing a go routine like this doesn't do anything - it's not monitored.

Error groups help us with this even if all they do is just make the semantics of working this a little easier. Error groups are actually implemented with wait groups under the hood. Instead of sync.waitgroup, we use sync.group from the x package. Instead of panicking on errors, we return them.

Look how much cleaner this is - we make an error group, we do eg.go a bunch of times and just return the error like it was any other function. And then we monitor to see if there's any errors that are returned by eg.wait. And if so, we can handle them.

Hopefully you can see why I like error groups - it adds the ability to have asynchronousness within your code but without adding a bunch of the reading overhead that comes with it. You don't make the mistake of not handling an error successfully and also you solve the issues of forgetting to call wg.done as well because it's handled for you.

The only warning I will give you about this is eg.wait returns the first error. So let's imagine you were making three calls - if the first one was successful and these two failed but this one failed first, you'd only know this one failed. For this reason, I recommend you only use error groups for getting information and not necessarily for anything that mutates. If you were making a request here and it wasn't idempotent, you might have changed the state of the world and not heard about it because you didn't get the errors back that you were expecting because one failed before the other.

I hope this is useful. Look forward to seeing what you do with error groups!