We may earn an affiliate commission when you visit our partners.
Course image
Udemy logo

Working with Concurrency in Go (Golang)

Trevor Sawler

Go, often referred to as Golang, is well-known for making it remarkably easy to work with concurrency. In order to make a particular function run concurrently, all we have to do is prepend the word "go" to the function call, and it cheerfully runs in the background, as a GoRoutine. Go's built in scheduler takes are of making sure that a given GoRoutine runs when it should, and as efficiently as it can.

Read more

Go, often referred to as Golang, is well-known for making it remarkably easy to work with concurrency. In order to make a particular function run concurrently, all we have to do is prepend the word "go" to the function call, and it cheerfully runs in the background, as a GoRoutine. Go's built in scheduler takes are of making sure that a given GoRoutine runs when it should, and as efficiently as it can.

However, this does not mean that working with concurrency is simple in Go—thread safe programming takes careful planning, and most importantly it requires that developers have an absolutely solid understanding of how Go deals with concurrency.

In the standard library, Go offers us several ways of dealing with concurrently running parts of our program, right in the standard library: sync.WaitGroup, which lets us wait for tasks to finish; sync.Mutex, which allows us to lock and unlock resources, so that no two GoRoutines can access the same memory location at the same time; and finally, Channels, which allow GoRoutines to send and receive data to and from each other.

Go's approach to concurrency is fairly straightforward, and is more or less summed up this mantra: Don't communicate by sharing memory; instead, share memory by communicating. Channels are the means by which we usually share memory by communicating.

In this course, we'll cover the use of WaitGroups, Mutexes, and Channels, and we'll do so in detail. We'll also cover some of the problems inherent in concurrency, including early program termination and race conditions. Initially, we'll gain a good understanding of how these things work by solving some of the classic problems found in the field of computer science, including the Dining Philosophers, the Producer/Consumer problem, and the Sleeping Barber. These problems are classics for a reason: they force a developer to figure out the best approach to working with code that run concurrently, or in parallel.

Finally, we'll finish the course out with a more "real-world" problem, where we have to register a customer for some kind of subscription service, and take care of invoicing, registration, and all the things necessary to get a new customer up and running. We'll do so, naturally, as quickly as we can by dividing the necessary tasks up into smaller tasks, and having them run concurrently.

Enroll now

What's inside

Learning objectives

  • Learn about the various ways go makes working with concurrent programing simple
  • Understand how concurrency works, and its advantages and pitfalls
  • Learn how waitgroups, mutexes, and channels work
  • Master concurrency by working with classic computer science problems, and by building a real-world example

Syllabus

An overview of the course, and installing the necessary software.

An overview of what we'll be doing in this course.

Just a bit of information about me and my background.

Read more

Obviously, we'll need Go installed. Let's make sure we have the latest version.

Chances are you already have an IDE installed, but if not, Visual Studio Code will do the job.

Installing Make

I'm happy to answer questions, but make it easy for me to give you the help you need.

No one is perfect, and that includes even experienced developers. I'll make mistakes, and I will not hide them.

There are several ways to work with concurrency in Go, and they all involve spawning goroutines with the "go" keyword. One method of working with goroutines is using WaitGroups. Let's look at them.
What we'll cover in this section

Let's have a look at the "go" keyword, which allows us to create goroutines for functions, and send them off to run concurrently with the main program. Let's also have a look at the problems that having things run concurrently can create, and figure out one (very bad!) way of solving such problems.

Let's get rid of the (awful) time.Sleep() call in our program, and instead take advantage of Go's built-in sync.WaitGroup type, which allows us to wait for one or more concurrently running tasks—GoRoutines—to finish before moving on.

Writing tests with WaitGroups
Challenge: working with WaitGroup
Solution to Challenge
Let's look at race conditions and how to address them, as well as the sync.Mutex package, and a brief introduction to Channels.

Race conditions occur when multiple GoRoutines attempt to access and modify the same data, and this leads to unpredictable results. Let's look at an example.

Adding sync.Mutex to our code

Go lets us test for race conditions when running a program, and when we write tests. Let's give this a try.

Let's write a slightly more complex program that gives us a race condition, and then use sync.Mutex to solve that problem.

Let's write a simple test for our weekly income program.

Waitgroups and Mutexes are wonderful tools, but let's add Channels to the mix by solving a classic computer science problem.

Let's get started with the Producer part of our solution to the Producer/Consumer problem.

Our producer is going to be producing pizzas, so let's write a function that will attempt to make a pizza.

Let's finish writing our Producer by completing the makePizza function, and listening for data sent to channels in the pizzeria function.

We have a Producer ready to go, but of course it has nothing to do until we create and run our Consumer. Let's take care of that now.

Let's put the finishing touches on our Producer/Consumer project.

Computer scientists love to give students highly contrived, complex problems to solve. One of these is the Dining Philosophers, which is perfect for learning about concurrency. Let's give it a look.

Let's have a look at another classic computer science problem: The Dining Philosophers.

Getting started with the problem
Implementing the diningProblem logic
Challenge: Printing out the order in which the meal is finished
Solution to challenge
Writing a test for our program
Let's have a more detailed look at Go channels, and let's also tackle another classic problem: the Sleeping Barber. This time, we'll solve the problem just using channels.

A gentle introduction to sending and receiving on channels.

Let's have a look at the select statement, which is more or less a switch statement, but for channels.

So far, every channel we have created has been unbuffered, so the channel can only hold one thing at a time (you can send as much information as you want to it, but sending will block until the channel is empty). Let's have a look at buffered channels, where we queue up more than one thing at a time for a given channel.

Let's write a few comments to get started with the Sleeping Barbers project.

In order to create a barbershop, we'll need a type which describes it, and a function to create it. Let's take care of that now. Let's also create a stub run() function that we'll use to start program execution.

Let's take care of adding a barber to the shop. This barber will be a method on the BarberShop type, and will take care of spawning a GoRoutine for that barber which will run until the shop closes for the day. Depending on what it receives from the ClientsChan channel, the barber associated with this GoRoutine will alternately nap and cut hair, depending on whether or not there is something sent to the ClientsChan channel.

So we can add barbers to the shop, and now we need to start another goroutine that waits until everything is done for the day. Let's get started.

Let's finish up our solution to the Sleeping Barber problem by sending clients the barbershop.

Let's try things out, and see how our solution works.

Let's build a more real-world scenario: a web application which allows users to purchase one of a variety of subscription services.

Just an overview of what we will do in this section of the course.

Let's write a bit of code and outline what we want to do in this application, and lets go and get the necessary packages for our database, sessions, and a router.

To make things simpler, let's get Docker installed, and bring up a Docker development environment with Postgres, Redis, and a dummy mail server.

Let's write the code necessary to connect to our Postgres database.

Setting up a Makefile will make our lives ever so much easier, so let's take care of that now.

We'll be using Alex Edward's session package with a Redis store in order to manage sessions for our web application. That mean's we'll need to set up a pool of Redis connections, and implement sessions for our application. Let's take care of that now.

Let's set up an application configuration type and variable that we can use to share configuration information with the various parts of our application.

Let's define a stub handler for the home page, set up a routes file, and start the web server.

Before we can display any pages on our site, we'll need to set up some templates and build a render function that parses and displays those templates. Let's get started.

Before we can hit a page on our web application, we'll need to set up a bit of middleware to load and save the session on every request. Let's take care of that now.

Let's set up a few more stub handlers and routes to them for the rest of our pages.

When we have an application that has goroutines running in the background, it's never a good idea to just stop everything abruptly when the application stops. Instead, we should take advantage of Go's concurrency features and shut down gracefully. Let's take care of that now.

Let's put some content into our database.

Let's install a data package that consists of models for our database tables, functions to interact with the database, and a simple means of making the models and functions available to our application.

Let's finish up the authentication portion of our web application, so that we can move on with some concurrency in the next section.

Sending Email Concurrently

In this section, we'll figure out how to send email behind the scenes, in its own GoRoutine.

In order to send email, we'll need some code that actually sends email messages. Let's get started.

Let's finish up the mailer.go file.

Let's make sure our code to send mail actually works by sending a message synchronously.

Let's write the code necessary to allow us to send email in the background.

Whenever we send an email concurrently, we'll need to increment the WaitGroup in our application config by 1. Let's make our lives simpler by writing a simple helper function that does that for us (because I know I'll forget, otherwise).

Let's update our Login handler to send an email notification to a user when there is a failed login attempt on their account.

Finally, let's update our shutdown() function to clean things up by closing the channels.

Let's update our handlers to allow users to register, activate their account, and display a page where they can buy a subscription.

We're going to be sending an activation email, so let's create the necessary templates, and let's also secure that email by signing the URL, which will make it tamper proof.

Let's write the handler to add a user, and to send that user an activation email.

Now that we can send an activation email, let's write the code necessary to make the user active after he or she clicks the link in the email.

Let's give all user data for an authenticated to user to our templates, in case we need it.

Let's get started with the page that will display available subscription packages to authenticated users, and allow them to purchase one.

Let's add a route to the plans page, and try things out.

Let's write a stub handler with some comments which will run when an authenticated user subscribes to a given plan.

Generating an invoice and manual might be time-intensive tasks, so let's generate them in the background.

Let's get started with our SubscribeToPlan handler.

Next, let's generate an invoice and email it to the customer.

Generating a manual

Let's try things out, fix a couple of mistakes, and subscribe a user to a plan.

Let's write a few tests for our code.

In order to test our project, we'll need to set up a testing environment first. Let's take care of that now.

Let's write a test to ensure that our routes are properly registered.

Let's write a test for our render.go file.

Let's modify our data package to use interfaces instead of concrete types, so that we can create  UserTest and PlanTest types which don't touch the database. That way, we can run unit tests without actually needing a running database.

Let's finish up our data package interfaces by implementing the methods necessary for PlanTest to satisfy the PlanInterface type.

Let's get started by writing some tests for our site pages.

Let's write a test for our login handler, and fix the way that we access the database in our handlers.

Finally, let's test a handler that makes use of concurrency, and update our setup_test.go file to decrement our WaitGroup when discarding emails.

Good to know

Know what's good
, what to watch for
, and possible dealbreakers
Designed for intermediate learners with some background knowledge in Go programming
Develops core foundational skills for concurrent programming in Go
Taught by Trevor Sawler, an experienced Go developer and instructor
Suitable for learners preparing for Go certification
Covers fundamental concepts such as wait groups, mutexes, and channels
May require prior experience in software development or programming

Save this course

Save Working with Concurrency in Go (Golang) to your list so you can find it easily later:
Save

Activities

Coming soon We're preparing activities for Working with Concurrency in Go (Golang). These are activities you can do either before, during, or after a course.

Career center

Learners who complete Working with Concurrency in Go (Golang) will develop knowledge and skills that may be useful to these careers:
Software Engineer
Software Engineers design, develop, and maintain software applications. As a Software Engineer, you may work with a variety of programming languages and technologies. This course will help you build a foundation in concurrency in Go, which is a key skill for Software Engineers who need to manage multiple tasks and processes efficiently.
Software Architect
Software Architects design and develop the overall architecture of software systems. As a Software Architect, you may work with high-level design patterns and principles. This course will help you build a foundation in concurrency in Go, which is a key skill for Software Architects who need to design and implement complex, scalable software systems.
Computer Programmer
Computer Programmers write and maintain computer programs. As a Computer Programmer, you may work with a variety of programming languages and technologies. This course will help you build a foundation in concurrency in Go, which is a key skill for Computer Programmers who need to manage multiple tasks and processes efficiently.
Backend Developer
Backend Developers build and maintain the server-side of web applications. As a Backend Developer, you may design and implement APIs, work with databases, and optimize application performance. This course will be useful in helping you understand the use of concurrency in Go, which is an essential skill for Backend Developers who need to coordinate multiple processes.
Data Engineer
Data Engineers build and maintain data pipelines that collect, process, and analyze large amounts of data. As a Data Engineer, you may work with big data technologies such as Hadoop and Spark. This course will help you build a foundation in concurrency in Go, which is an essential skill for Data Engineers who need to manage and process large datasets efficiently.
Cloud Architect
Cloud Architects design, build, and manage cloud computing systems. As a Cloud Architect, you may work with multiple cloud platforms, such as AWS, Azure, and Google Cloud. This course will help you build a foundation in concurrency in Go, which is a key skill for Cloud Architects who need to design and manage scalable, high-performance cloud systems.
DevOps Engineer
DevOps Engineers bridge the gap between development and operations teams. As a DevOps Engineer, you may work on automating build, deployment, and testing processes. This course will help you build a foundation in concurrency in Go, which is a key skill for DevOps Engineers who need to design and implement automated systems.
Web Developer
Web Developers design and develop websites and web applications. As a Web Developer, you may work with HTML, CSS, JavaScript, and other web technologies. This course will help you build a foundation in concurrency in Go, which is a useful skill for Web Developers who need to manage multiple requests and processes on the web.
Machine Learning Engineer
Machine Learning Engineers design and develop machine learning models. As a Machine Learning Engineer, you may work with a variety of machine learning algorithms and techniques. This course may be useful in building a foundation in concurrency in Go. Concurrency is a somewhat niche topic for a Machine Learning Engineer, but a skilled Machine Learning Engineer should have a passing familiarity with concurrency.
Mobile Developer
Mobile Developers design and develop mobile applications for smartphones and tablets. As a Mobile Developer, you may work with native programming languages such as Java and Swift, or with cross-platform frameworks such as React Native. This course will help you build a foundation in concurrency in Go, which is a useful skill for Mobile Developers who need to manage multiple tasks and processes on mobile devices.
Technical Writer
Technical Writers create and maintain documentation for software and hardware products. As a Technical Writer, you may work with a variety of writing and editing tools. This course may be useful in helping you understand the use of concurrency in Go, which is a key concept in modern software development.
Network Engineer
Network Engineers design, build, and maintain computer networks. As a Network Engineer, you may work with network protocols, routing, and switching. This course may be useful in building a foundation in concurrency in Go. Concurrency is a somewhat niche topic for a Network Engineer, but a skilled Network Engineer should have a passing familiarity with concurrency.
Quality Assurance Engineer
Quality Assurance Engineers test and validate software applications. As a Quality Assurance Engineer, you may work with manual and automated testing techniques. This course may be useful in building a foundation in concurrency in Go. Concurrency is a somewhat niche topic for a Quality Assurance Engineer, but a skilled Quality Assurance Engineer should have a passing familiarity with concurrency.
Security Engineer
Security Engineers design and implement security measures to protect computer systems and networks. As a Security Engineer, you may work with encryption, authentication, and access control. This course may be useful in building a foundation in concurrency in Go. Concurrency is a somewhat niche topic for a Security Engineer, but a skilled Security Engineer should have a passing familiarity with concurrency.
Systems Administrator
Systems Administrators manage and maintain computer systems and networks. As a Systems Administrator, you may work with operating systems, hardware, and virtualization. This course may be useful in building a foundation in concurrency in Go. Concurrency is a somewhat niche topic for a Systems Administrator, but a skilled Systems Administrator should have a passing familiarity with concurrency.

Reading list

We've selected six books that we think will supplement your learning. Use these to develop background knowledge, enrich your coursework, and gain a deeper understanding of the topics covered in Working with Concurrency in Go (Golang).
Great reference for developers who want to learn more about concurrency in Go. It covers a wide range of topics, from the basics of concurrency to more advanced techniques like channels and synchronization.
Great resource for learning the Go programming language. It covers all the basics of the language, including concurrency.
Great resource for developers who want to learn about the fundamentals of designing data-intensive applications. It covers a wide range of topics, including concurrency.
Great resource for developers who want to learn more about the Go programming language. It covers a wide range of topics, including concurrency.

Share

Help others find this course page by sharing it with your friends and followers:

Similar courses

Here are nine courses similar to Working with Concurrency in Go (Golang).
Our mission

OpenCourser helps millions of learners each year. People visit us to learn workspace skills, ace their exams, and nurture their curiosity.

Our extensive catalog contains over 50,000 courses and twice as many books. Browse by search, by topic, or even by career interests. We'll match you to the right resources quickly.

Find this site helpful? Tell a friend about us.

Affiliate disclosure

We're supported by our community of learners. When you purchase or subscribe to courses and programs or purchase books, we may earn a commission from our partners.

Your purchases help us maintain our catalog and keep our servers humming without ads.

Thank you for supporting OpenCourser.

© 2016 - 2024 OpenCourser