Goroutines Flashcards

(10 cards)

1
Q

Goroutine Basics

A

Definition:
Lightweight thread managed by the Go runtime (not OS threads).
Starts with:

go func() {
    fmt.Println("Running concurrently!")
}()

Key Traits:
* ~2KB stack (grows dynamically)
* Scheduled by Go runtime (M:N threading)
* Cheap to create (thousands are practical)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Goroutine vs Thread

A

Feature Goroutine OS Thread
Memory ~2KB initial ~1MB+ (default)
Creation Fast (runtime) Slow (OS)
Switch Runtime-managed Kernel-managed
Cost Thousands feasible Hundreds limited

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Synchronization (WaitGroup)

A

Block until done:

var wg sync.WaitGroup
wg.Add(1)  // Set counter

go func() {
    defer wg.Done()  // Decrement counter
    // Work...
}()

wg.Wait()  // Blocks until counter=0

Use Case: Wait for N goroutines to complete.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Channels (Basic)

A

Create:

ch := make(chan int)  // Unbuffered
chBuffered := make(chan string, 3)  // Buffered

Send/Receive:

ch <- 42       // Send  
val := <-ch    // Receive (blocks)  
val, ok := <-ch  // Check if channel closed  
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Select Statement

A

Multiplex channels:

select {
case msg := <-ch1:
    fmt.Println(msg)
case ch2 <- time.Now():
    // Sent time
case <-time.After(1 * time.Second):
    fmt.Println("Timeout")
default:
    // Non-blocking fallthrough
}

Rules:

Random selection if multiple ready

default prevents blocking

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Worker Pool Pattern

A
jobs := make(chan int, 100)
results := make(chan int, 100)

// Start 3 workers
for w := 1; w <= 3; w++ {
    go func(id int) {
        for job := range jobs {
            results <- job * 2
        }
    }(w)
}

// Send jobs
for j := 1; j <= 5; j++ {
    jobs <- j
}
close(jobs)

// Collect results
for r := 1; r <= 5; r++ {
    fmt.Println(<-results)
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Common Pitfalls

A

Leaking Goroutines:

go func() {
    for { /* runs forever */ }
}()  // No way to stop!
Fix: Use context or done channels.

Race Conditions:

var counter int
go func() { counter++ }()
go func() { counter++ }()  // Data race!

Fix: Use sync.Mutex or channels.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Context + Goroutines

A

Graceful shutdown:

ctx, cancel := context.WithCancel(context.Background())
go func() {
    <-ctx.Done()  // Triggered on cancel()
    fmt.Println("Stopped cleanly")
}()
cancel()  // Signal cancellation
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Benchmarking Goroutines

A

Test creation cost:

func BenchmarkGoroutine(b *testing.B) {
    for i := 0; i < b.N; i++ {
        go func() {}()  // Measure overhead
    }
}

Typical result: ~300ns per goroutine on modern hardware

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Golden Rules

A
  1. Don’t ignore goroutine errors (use error channels)
  2. Always clean up resources (avoid leaks)
  3. Prefer channels over shared memory
  4. Use sync.WaitGroup for coordination
  5. Monitor goroutine counts in production
How well did you know this?
1
Not at all
2
3
4
5
Perfectly