0

Go Concurrency Concept

When I first started learning Go, everyone kept saying:

"Just use goroutines."

But that didn't really explain anything.

I could write: go sendEmail() and it worked

But then questions started appearing:

What happens if it fails? How do I stop it? What if I create 10,000 of them? How do real applications handle background jobs?

It wasn't until I stopped thinking about goroutines as "Go magic" and started thinking about them as workers in a kitchen (with a bit of Q&A with AI to help me understand it more simply 🫡)

1. A Kitchen

Imagine you're running a restaurant.

You have:

Cooks
Order tickets
A rail where tickets are placed

In Go:

Cook = Goroutine
Order Ticket = Channel Message
Ticket Rail = Channel
Kitchen Team = Worker Pool

A customer places an order then the ticket goes onto the rail. Whichever cook is free picks it up.

That's basically how many Go backends work.

2. Goroutines Are Just Workers

The simplest goroutine looks like this:

go updateReadingStats(bookID)

That tells Go: "Start another worker and let them handle this."

Meanwhile, the main program keeps moving. It's simple and incredibly powerful.

But there's a catch.

If that worker crashes, nobody is waiting for the result. The error can disappear silently.

That's why production systems usually add logging, panic recovery, and cancellation support.

Starting work is easy. Managing work is the hard part.

3. Channels Are the Secret Sauce

A channel is just a safe way for goroutines to talk.

jobs <- "process-book"

One goroutine sends and another receives.

job := <-jobs

That's it. No mutexes. No complicated synchronization.

Just passing messages.

I like to think of channels as the ticket rail in the kitchen. Workers don't need to know who created the ticket. They only care that there's work available.

4. Worker Pools: Controlled Chaos

for _, book := range books { 
    go processBook(book) 
}

With 10,000 books, this code creates thousands of workers concurrently, which could overwhelm the system. Databases, APIs, and storage systems usually don't enjoy that.

Instead of creating unlimited workers, create a fixed number worker. Every new job goes into the queue. Whichever worker becomes available takes the next one.

It's like having three cooks in the kitchen. No matter how many orders arrive, you never suddenly hire 5,000 cooks.

This idea is called bounded concurrency, and it's one of the most useful concepts in backend engineering.

Example: Imagine someone uploads a file, like an Epub. A lot needs to happen:

Upload Book 
    ↓
Extract Metadata
    ↓
Generate Cover
    ↓
Index Search
    ↓
Update Statistics
    ↓
    ...

You don't want the user waiting for all of that. We can change a little bit with worker pools:

User Uploads Book -> Create Job -> Worker Pool -> Background Processing

The upload finishes instantly. The heavy work happens behind the scenes. This is the same idea used in many production systems.

I'd love to hear your thoughts — drop a comment below to support the channel and start a discussion!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí