Concurrency
129 articles
Buffered vs unbuffered channels
Buffered channels store values in memory to prevent blocking, while unbuffered channels require immediate synchronization between sender and receiver.
Buffered vs Unbuffered Channels in Go
Use buffered channels for os.Signal to prevent missing signals and fix sigchanyzer vet errors.
Channel direction in function signatures
Use <-chan T for receive-only and chan<- T for send-only channels in Go function signatures to enforce unidirectional data flow.
Channel Patterns: Generator, Fan-Out, Fan-In, Pipeline
Go channel patterns like Generator, Fan-Out, Fan-In, and Pipeline are concurrency designs implemented with goroutines and channels to manage data flow efficiently.
Common Channel Mistakes and Deadlocks in Go
Prevent Go deadlocks by ensuring channel operations have matching sends and receives or using buffered channels.
Common Concurrency Bugs in Go and How to Find Them
Most concurrency bugs in Go stem from data races (unsynchronized access to shared variables) or deadlocks caused by improper channel or mutex usage.
Common Goroutine Mistakes and How to Avoid Them
Avoid goroutine mistakes like data races and leaks by using channels, mutexes, and WaitGroups to manage concurrency safely.
Complete Guide to the sync Package in Go
The sync package provides basic synchronization primitives like Mutex, WaitGroup, and Once for coordinating goroutines in Go.
Fan-out fan-in pattern with channels
The fan-out fan-in pattern uses goroutines and a shared queue to parallelize function compilation in the Go compiler.
Fix: "all goroutines are asleep - deadlock!"
Fix the "all goroutines are asleep - deadlock!" error by ensuring at least one goroutine can proceed by sending on channels or releasing locks.
Fix: "all goroutines are asleep - deadlock!" in Go
Fix the Go deadlock error by ensuring all goroutines are started with 'go' and channel operations have matching senders and receivers.
Fix: "all goroutines are asleep - deadlock!" with Channels
Fix the 'all goroutines are asleep - deadlock!' error by ensuring every channel send has a matching receive operation to prevent blocking.
Fix: "concurrent map writes" in Go
Fix the concurrent map writes panic in Go by wrapping all map access with a sync.Mutex to ensure thread-safe operations.
Fix: "concurrent map writes" Panic in Go
Fix the 'concurrent map writes' panic by wrapping map access in a sync.Mutex to serialize operations.
Fix: "fatal error: concurrent map read and map write"
Fix the 'concurrent map read and map write' panic by wrapping all map access with a sync.Mutex or sync.RWMutex.
Fix: "race condition detected" by Go Race Detector
Enable the Go Race Detector by running tests or builds with the -race flag to identify and fix concurrent memory access issues.
Fix: "send on closed channel" in Go
Fix the 'send on closed channel' panic by ensuring the channel is not closed until all goroutines have finished sending data.
Fix: "send on closed channel" Panic in Go
Fix 'send on closed channel' panic by ensuring channels are closed only once and checking state before sending.
Go Concurrency Patterns: A Comprehensive Guide
Go concurrency patterns use goroutines and channels to coordinate tasks, as shown by the Fibonacci pipeline example.
Go Idioms: Don't Communicate by Sharing Memory; Share Memory by Communicating
This idiom means you should avoid using mutexes and shared variables to coordinate goroutines; instead, pass data directly between goroutines using channels.
Goroutines vs Threads: What Is the Difference
Goroutines are lightweight, runtime-managed concurrency units in Go, while threads are heavier, OS-managed execution units.
How Channel Internals Work in Go (hchan Struct)
Go channels are implemented via the hchan struct in src/runtime/chan.go, managing buffers, wait queues, and synchronization locks.
How do channels work
Channels are typed conduits for safe communication between goroutines using send and receive operations.
How do goroutines work in Go
Goroutines are lightweight concurrent functions in Go launched with the 'go' keyword to run tasks simultaneously.
How Go Channels Work Internally (hchan, sudog)
Go channels use an hchan struct with a circular buffer and sudog wait queues to synchronize goroutines safely.
How Goroutine Scheduling Preemption Works in Go
Go preempts goroutines at compiler-identified safe points to ensure fair CPU scheduling and responsiveness.
How Goroutine Stack Growth Works in Go
Go goroutine stacks grow and shrink automatically at runtime to optimize memory usage for concurrent tasks.
How Go select Works Internally
Go's select statement blocks until one channel operation is ready, then executes that single operation pseudo-randomly if multiple are available.
How Many Goroutines Can You Run in Go
Go has no hard limit on goroutines, allowing millions to run concurrently limited only by system memory and CPU cores.
How much memory does a goroutine use
Goroutines start with a 2 KB stack that grows and shrinks dynamically to optimize memory usage.
How the Go Scheduler Works (GMP Model)
The Go scheduler uses the GMP model to efficiently run millions of goroutines on limited OS threads by dynamically balancing work and handling blocking operations.
How the Go Scheduler Works: G, M, P Model
The Go scheduler uses the GMP model to map Goroutines to OS threads via logical processors for efficient, balanced concurrency.
How to Avoid Race Conditions in Go
Prevent Go race conditions by using sync.Mutex or sync.RWMutex to lock shared variables during read or write operations.
How to Check If a Channel Is Closed in Go
Check if a Go channel is closed by using a select statement with a default case to detect immediate zero-value returns.
How to close a channel
Close a channel using the built-in `close()` function, but only when you are certain no more values will be sent and all receivers have finished processing.
How to Close a Channel in Go (And Why It Matters)
Close a Go channel with close(ch) to signal completion and allow receivers to exit loops gracefully.
How to Create and Use Channels in Go
Create channels using the `make` function with the `chan` type, then send data into them with the `<-` operator and receive data from them with the same operator.
How to Create a Thread-Safe Map in Go with sync.Map
Use `sync.Map` when you need a concurrent map for read-heavy workloads or when keys are short-lived, but prefer a standard `map` protected by a `sync.Mutex` for write-heavy scenarios or when you need to iterate over all keys.
How to Create a Worker Pool in Go with Channels
Create a Go worker pool by spawning goroutines that consume tasks from a buffered channel and wait for completion with sync.WaitGroup.
How to Debug Goroutine Leaks in Go
Debug goroutine leaks in Go by capturing a profile with runtime/pprof and analyzing the stack traces using go tool pprof.
How to Fan Out and Fan In with Channels in Go
Fan out distributes tasks to goroutines via a shared channel, and fan in aggregates results back into a single stream.
How to Get the Current Number of Running Goroutines
Get the current number of running goroutines in a Go program using the runtime.NumGoroutine() function.
How to handle panics in goroutines
Prevent goroutine panics from crashing your Go program by wrapping the goroutine logic in a defer function that calls recover().
How to Handle Partial Failures in Concurrent Go Code
Handle partial failures in Go by checking errors per goroutine, using channels for propagation, and canceling remaining work via context.
How to Implement a Leaky Bucket Rate Limiter in Go
Use the `golang.org/x/time/rate` package to implement a leaky bucket rate limiter in Go.
How to Implement a Thread-Safe Counter in Go
Implement a thread-safe counter in Go by wrapping an integer with a sync.Mutex to lock access during read and write operations.
How to Implement a Thread-Safe Singleton in Go
Go does not have a traditional "thread-safe singleton" pattern like Java or C++ because the language's concurrency model and memory guarantees make explicit locking unnecessary for initialization.
How to Implement a Timeout with Channels and select
Implement a timeout in Go by using time.After with a select statement to handle completion or expiration.
How to Implement a Token Bucket Rate Limiter in Go
Implement a token bucket rate limiter in Go using the golang.org/x/time/rate package to control request frequency.
How to Implement Bounded Parallelism in Go
Implement bounded parallelism in Go by using a buffered channel as a semaphore to control the number of active goroutines.
How to Implement Cancellation Propagation Trees in Go
Implement cancellation propagation in Go by passing a shared context to child goroutines and using errgroup to cancel all tasks on the first error.
How to Implement Graceful Shutdown Pattern in Go
Implement graceful shutdown in Go by catching OS signals, canceling a context with a timeout, and calling server.Shutdown to finish active requests.
How to Implement Pub/Sub with Channels in Go
Implement Go Pub/Sub by creating a channel with make(), sending data via goroutines, and receiving it with the <- operator.
How to Implement Rate Limiting with time.Ticker in Go
Implement rate limiting in Go by creating a time.Ticker and looping over its channel to enforce fixed time intervals between actions.
How to Implement Request-Scoped Goroutine Lifetimes
Manually manage goroutine lifetimes in Go by passing a context.Context to the goroutine and calling cancel() when the request completes.
How to Implement Supervisor Trees in Go
Implement supervisor trees in Go by using goroutines, channels, and context to monitor and restart child processes.
How to Implement the Bridge Channel Pattern in Go
Implement the Bridge Channel Pattern in Go by creating a struct with a channel field to decouple data producers from consumers.
How to Implement the Context-Based Cancellation Pattern
Implement context-based cancellation in Go by deriving child contexts and checking ctx.Done() to stop tasks immediately.
How to Implement the Fan-Out/Fan-In Pattern in Go
Implement Fan-Out/Fan-In in Go by spawning goroutines to process items from a shared channel and sending results to a results channel, then closing the results channel once all workers finish.
How to Implement the Or-Channel Pattern in Go
Implement the Or-Channel pattern in Go by using a select statement within a goroutine to return the first value received from multiple input channels.
How to Implement the Pipeline Pattern in Go
Implement the pipeline pattern in Go by chaining goroutines that pass data through channels to process streams concurrently.
How to Implement the Publish-Subscribe Pattern in Go
Implement the Publish-Subscribe pattern in Go using channels and a Topic struct to decouple message producers from multiple consumers.
How to Implement the Reader-Writer Lock Pattern in Go
Implement the Reader-Writer lock pattern in Go using sync.RWMutex to manage concurrent read and write access safely.
How to Implement the Semaphore Pattern in Go
Implement the semaphore pattern in Go using the golang.org/x/sync/semaphore package to limit concurrent operations.
How to Implement the Tee Channel Pattern in Go
The Tee Channel pattern is implemented by creating a goroutine that reads from a source channel and writes to multiple destination channels until the source closes.
How to Implement the Worker Pool Pattern in Go
Implement a Go worker pool using a fixed number of goroutines, a buffered job channel, and a result channel managed by a WaitGroup.
How to Implement Timeout Patterns in Go
Implement Go timeouts by wrapping operations in a context created with context.WithTimeout and checking for context.DeadlineExceeded errors.
How to limit concurrent goroutines
Limit concurrent goroutines in Go by using a buffered channel as a semaphore to control access.
How to Limit the Number of Concurrent Goroutines
Limit concurrent goroutines in Go by using a buffered channel as a semaphore to control access to a shared resource.
How to Pipeline Data with Channels in Go
Pipe data between Go goroutines safely by sending values into a channel and receiving them with a range loop.
How to Range Over a Channel in Go
You range over a channel by using the `for range` loop, which automatically receives values until the channel is closed.
How to range over channel
You range over a channel by using a `for` loop with the `range` keyword, which automatically iterates through received values until the channel is closed.
How to Start a Goroutine in Go
Start a goroutine by prefixing a function call with the `go` keyword, which runs that function concurrently in a new lightweight thread managed by the Go runtime.
How to Stop a Goroutine in Go
Goroutines cannot be forcibly stopped; they must be signaled via context or channels to exit gracefully.
How to Use a Done Channel to Signal Completion
Signal task completion in Go by closing a done channel and waiting on it with a receive operation.
How to use atomic operations
Use the `sync/atomic` package when you need lock-free, thread-safe updates to simple variables like integers, pointers, or booleans, avoiding the overhead of `sync.Mutex` for high-frequency counters or flags.
How to Use atomic.Value in Go
Use sync/atomic.Value to safely share a single value across multiple goroutines without explicit locking.
How to Use Channels as Semaphores in Go
Use a buffered channel with a capacity equal to the desired concurrency limit, where acquiring a permit means sending a value into the channel and releasing it means receiving a value.
How to Use conc Library for Safer Concurrency in Go
The `conc` library provides a lightweight, zero-allocation wrapper around Go's standard concurrency primitives to prevent common race conditions and goroutine leaks without sacrificing performance.
How to Use context.Background and context.TODO
Use context.Background() for top-level contexts and context.TODO() as a temporary placeholder when the correct context is unknown.
How to use context for goroutine cancellation
Use context.WithCancel to create a cancellable context and check ctx.Done() inside goroutines to stop execution gracefully.
How to Use context.WithCancel in Go
Create a cancellable context with context.WithCancel and call the returned cancel function to stop operations.
How to Use context.WithDeadline in Go
context.WithDeadline creates a context that cancels at a specific time and returns a cancel function to stop it early.
How to Use context.WithTimeout in Go
Create a context with a deadline using context.WithTimeout to automatically cancel operations after a set duration.
How to Use context.WithValue in Go (And When Not To)
Use context.WithValue to pass small, request-scoped data through goroutine boundaries, but avoid it for large objects or data that can be passed as explicit arguments.
How to Use Directional Channels (chan<- and <-chan) in Go
Use chan<- T for send-only and <-chan T for receive-only channels to restrict data flow direction in Go.
How to use errgroup
Use golang.org/x/sync/errgroup to run concurrent goroutines that stop on the first error and return that error when waiting.
How to Use errgroup for Concurrent Tasks in Go
Use errgroup.WithContext and g.Go to run concurrent tasks that cancel automatically on the first error.
How to Use errgroup for Structured Concurrency
Use golang.org/x/sync/errgroup to run concurrent goroutines that automatically cancel on the first error.
How to Use errgroup for Structured Concurrency in Go
Use errgroup.WithContext to run parallel goroutines that cancel automatically on the first error.
How to Use Goroutine-Safe Data Structures
Use sync.Mutex to wrap standard types or sync.Map for concurrent access in Go, as no built-in goroutine-safe collections exist.
How to Use runtime.GOMAXPROCS in Go
Use `runtime.GOMAXPROCS(0)` to let Go automatically set the number of OS threads to match your machine's logical CPU cores, which is the recommended default for most applications.
How to Use runtime.Gosched and runtime.Goexit
runtime.Gosched yields the processor to other goroutines, while runtime.Goexit terminates the current goroutine immediately.
How to Use select Statement in Go (Channel Multiplexing)
Use the select statement with case clauses to block until one of multiple channels is ready for communication.
How to use select with channels
Use the select statement to wait on multiple channel operations simultaneously, executing the first one that becomes ready.
How to Use semaphore.Weighted for Concurrency Limiting
Use golang.org/x/sync/semaphore.NewWeighted to limit concurrency by acquiring and releasing weighted tokens.
How to Use singleflight to Deduplicate Concurrent Calls
Use internal/singleflight.Group.Do to deduplicate concurrent function calls by key, ensuring only one execution runs while others wait for the shared result.
How to Use sync/atomic Package in Go
Use sync/atomic for fast, lock-free updates to int64, uint64, and pointer variables in concurrent Go programs.
How to Use sync.Cond in Go
Use sync.Cond to block goroutines on a condition variable by wrapping a mutex and signaling changes with Signal or Broadcast.
How to use sync Map
Use sync.Map for concurrent read-heavy workloads by initializing it and using Load, Store, and Delete methods.
How to Use sync.Map in Go (Thread-Safe Map)
Use sync.Map for high-concurrency, read-heavy scenarios to avoid the performance penalty of locking a standard map.
How to Use sync.Mutex and sync.RWMutex in Go
Use sync.Mutex for exclusive access to shared data and sync.RWMutex to allow multiple readers but only one writer at a time.
How to Use sync.Once in Go for One-Time Initialization
Use sync.Once with the Do method to safely execute initialization code exactly once in concurrent Go programs.
How to use sync Pool
Use sync.Pool to cache and reuse objects by calling Get() to retrieve and Put() to return them, reducing allocation overhead.
How to Use sync.Pool in Go for Object Reuse
Use sync.Pool to cache and reuse objects, reducing allocation overhead and garbage collection frequency.
How to Use sync.WaitGroup in Go
sync.WaitGroup blocks the main goroutine until all launched goroutines call Done() to signal completion.
How to Use the Go Race Detector (-race Flag)
Use the -race flag with go run or go test to detect data races in your Go program.
How to Use the select Statement with Channels in Go
The select statement in Go allows concurrent waiting on multiple channel operations, executing the first one that is ready.
How to Wait for Goroutines to Finish with sync.WaitGroup
Use `sync.WaitGroup` to synchronize goroutines by incrementing its counter before launching each one and calling `Done()` when they finish, then block the main thread with `Wait()` until the counter reaches zero.
How to wait for goroutines with WaitGroup
Use `sync.WaitGroup` to track a set of goroutines by incrementing the counter before launching each one and decrementing it when finished, then call `Wait()` to block until the counter reaches zero.
Mutex vs Channel: When to Use Which in Go
Use Mutexes to protect shared variables from concurrent access and Channels to pass data between goroutines without sharing state.
Nil channel usage
Initialize channels with make() to prevent indefinite blocking caused by nil channel operations.
Patterns for Bounded Concurrency with Context in Go
Limit concurrent goroutines in Go using a buffered channel semaphore and context for cancellation.
The Goroutine Closure Variable Capture Gotcha
Fix Go goroutine closure variable capture by declaring a new variable inside the loop to snapshot the current iteration value.
The time.After Memory Leak in select Loops
Fix time.After memory leaks in select loops by using time.NewTimer and calling Stop() to prevent uncanceled timers from accumulating in memory.
What Are Channels in Go and How Do They Work
Channels are typed conduits that allow goroutines to communicate by sending and receiving values, acting as the primary synchronization mechanism in Go.
What Are Goroutines in Go and How Do They Work
Goroutines are lightweight, concurrent functions in Go launched with the 'go' keyword to run tasks in parallel.
What happens sending to closed channel
Sending to a closed channel immediately panics your program, terminating the goroutine and potentially crashing the entire application.
What Happens When the main Goroutine Exits
When the main goroutine exits, the Go program terminates instantly, killing all other goroutines regardless of their state.
What Is a Data Race vs a Race Condition in Go
A data race is a specific type of race condition involving unsynchronized concurrent memory access, detectable in Go using the -race flag.
What Is a Goroutine Leak and How to Prevent It
A goroutine leak is a non-terminating background task that consumes resources, prevented by ensuring every goroutine has a clear exit condition via context cancellation or channel closure.
What Is a Nil Channel and How to Use It
A nil channel is a channel variable that has been declared but never initialized with `make`, meaning it has no underlying buffer or communication mechanism.
What Is context.Context in Go and Why It Matters
context.Context manages deadlines, cancellation, and request values across Go goroutines to prevent resource leaks.
What is goroutine leak and how to prevent it
A goroutine leak is a non-terminating goroutine that consumes resources, prevented by ensuring clear exit conditions via context cancellation or channel closure.
What Is Structured Concurrency and How Go Approaches It
Structured concurrency ensures child goroutines finish with their parent, implemented in Go using WaitGroup and Context.
What is the difference between goroutines and threads
Goroutines are lightweight, runtime-managed concurrent units, while threads are heavier, kernel-managed execution units that goroutines multiplex onto.
What Is the Difference Between Mutex and RWMutex in Go
Mutex allows exclusive access for any operation, while RWMutex permits multiple concurrent readers but exclusive access for writers.
When to Use Channels vs Mutexes in Go
Use channels for communication between goroutines and mutexes for protecting shared data from concurrent access.
Worker pool with channels
A worker pool uses channels to distribute tasks to a fixed number of goroutines for safe, concurrent processing.