All PatternsConcurrency
Semaphore
Controls access to resources by multiple goroutines.
Connection limitingRate limitingResource pooling
Understanding Semaphore
The Semaphore pattern controls access to a shared resource by maintaining a count of available permits. Unlike a mutex (which allows only one goroutine), a semaphore allows up to N goroutines to access a resource concurrently. In Go, a semaphore is elegantly implemented using a buffered channel — acquiring a permit sends to the channel (blocking when full), and releasing reads from it. This pattern is essential for connection pooling, rate limiting, and controlling concurrent access to external services like databases or third-party APIs.
Key Concepts
- •Counting semaphore — allows up to N concurrent accesses, unlike a mutex which allows only 1
- •Buffered channel as semaphore — Go idiom: a chan struct with capacity N naturally limits concurrency
- •Acquire and Release — send to acquire a permit (blocks when full), receive to release it
- •Resource protection — prevents overwhelming external services by capping concurrent requests
When to Use
✅ Use when
- • You need to limit concurrent access to a shared resource (DB, API, file)
- • You want to implement rate limiting for outbound requests
- • A connection pool needs to cap the number of active connections
- • You need more flexibility than a simple mutex (allowing N concurrent users)
⚠️ Avoid when
- • You only need exclusive access (use sync.Mutex instead)
- • Go\'s runtime and scheduler already handle the concurrency well
- • A worker pool pattern gives you more control over the processing
Structure
Goroutines (many)
↓ Acquire()
Semaphore (buffered chan, cap=N)
↓ Release()
Protected Resource
How It Works
Goroutines
G1
G2
G3
G4
G5
Semaphore (max: 3)
○
○
○
0/3 slots used
Resource
💤 Idle
5 goroutines want access
1
Goroutines Waiting
Multiple goroutines want to access a limited resource.
1 / 4
Basic Implementation
Simple semaphore with acquire/release:
main.go
Loading editor...
Real-World Example: Rate Limiter
API rate limiting with semaphore:
main.go
Loading editor...