Goroutines and Concurrency
# CHAPTER 19
Goroutines and Concurrency
1. Introduction
Modern CPUs have 8, 16, or even 64 cores. Traditional code executes sequentially—one line after another on a single core—wasting 90% of your computer's power. Concurrency is the ability to do multiple things at the same time.In languages like Java or C++, you create OS Threads to achieve this, which are heavy, memory-intensive, and hard to manage. Go was built from the ground up to solve this. Go uses Goroutines—incredibly lightweight, virtual threads that make writing concurrent code effortless.
2. Learning Objectives
By the end of this chapter, you will be able to:- Understand Concurrency vs. Parallelism.
-
Spawn a Goroutine using the
gokeyword.
- Understand how the Go Scheduler manages execution.
-
Recognize the problem of the
mainfunction exiting too early.
-
Use
time.Sleepas a basic synchronization method.
3. Concurrency vs Parallelism
- Concurrency: Dealing with many things at once (e.g., A chef chopping onions, then stirring soup, then going back to onions).
- Parallelism: Doing many things at exactly the same time (e.g., Two chefs: one chops onions, the other stirs soup).
Go excels at Concurrency. By breaking tasks into Goroutines, the Go runtime automatically distributes them across all available CPU cores, naturally achieving Parallelism!
4. What is a Goroutine?
A Goroutine is a function executing concurrently with other goroutines in the same address space.- An OS Thread takes about 1MB of memory. You can only run a few thousand before crashing your server.
- A Goroutine takes only 2KB of memory. You can easily run 100,000 Goroutines on a standard laptop simultaneously!
5. Spawning a Goroutine
To run a function concurrently, simply place the keywordgo in front of the function call.
Let's look at sequential code first:
Now, let's make it Concurrent!
*Output:*
Notice how they print at the exact same time!
6. The "Main" Goroutine Rule
Themain() function is a Goroutine itself.
CRITICAL RULE: When the main() Goroutine finishes and reaches its closing brace }, the entire program terminates instantly, destroying all other active Goroutines.
This is why we had to add time.Sleep in the example above. If we didn't, main would spawn the two tasks and immediately close the program before the sheep or cows had a chance to print anything!
7. Visualizing the Goroutine Flow
8. The Go Scheduler
You don't have to manually assign Goroutines to CPU cores. The Go Scheduler is a genius piece of software built into the Go runtime. It looks at your available CPU cores and rapidly multiplexes thousands of Goroutines across them automatically.9. Common Mistakes
-
Forgetting to Wait: Using the
gokeyword but wondering why the program finishes instantly without printing any output. (Themainfunction finished too fast).
-
Using
time.Sleepin Production:time.Sleepis great for tutorials, but in the real world, you never know exactly how long a database query or network request will take. Sleeping for an arbitrary amount of time is terrible practice. (We will learn the proper way to wait usingWaitGroupsandChannelsin the next chapters).
10. Best Practices
- Keep it Lightweight: Feel free to spawn thousands of Goroutines! Go is specifically designed to handle them. For example, a Go web server automatically spawns a brand new Goroutine for every single incoming HTTP request.
11. Exercises
-
1.
Write a function
printNumbers()that prints 1 to 5 with a 100ms sleep.
-
2.
Write a function
printLetters()that prints A to E with a 100ms sleep.
-
3.
Call both in
main()using thegokeyword, and add a sleep inmainto ensure they finish. Observe the interleaved output.
12. MCQs with Answers & Explanations
What is Concurrency?
What is a Goroutine?
How much memory does a new Goroutine roughly consume?
How do you trigger a function to run concurrently in a new Goroutine?
What happens when the main() function finishes its last line of code?
What component of Go automatically distributes Goroutines across your multi-core CPU?
If you run go taskA() and go taskB(), which one will finish first?
time.Sleep() the recommended way to wait for Goroutines to finish in production code?
a) Yes b) No, because you cannot predict exactly how long a task will take
Answer: b) No.
What automatically happens when a Go web server receives an incoming HTTP request?
13. Interview Preparation
Interview Questions:- 1. Contrast Goroutines with traditional OS Threads (Memory footprint, management).
-
2.
What happens if a Goroutine is running, but the
mainGoroutine exits?
- 3. Explain the difference between Concurrency and Parallelism.
14. Summary
Goroutines are the crown jewel of the Go language. By simply typing the wordgo, you unlock the full multi-core power of modern processors. However, because they execute independently, they introduce a new problem: synchronization. How do we know when they are done? How do they share data without overwriting each other?
15. Next Chapter Recommendation
Currently, our Goroutines are deaf and blind; they cannot talk tomain or to each other. In Chapter 20: Channels in Go, we will introduce the mechanism that allows Goroutines to safely send and receive data between themselves.