Pattern trong Go
Runtime và thư viện chuẩn của Go cho thấy các triển khai pattern gọn gàng, thực tế.
| Pattern | Ở đâu trong Go | Tác dụng |
|---|---|---|
| Cooperative Scheduling | runtime/proc.go | Lập lịch goroutine với điểm preemption hợp tác |
| Bitmask | os/types.go | FileMode — flag phân quyền Unix qua hằng có kiểu với iota |
| Object Pool | sync/pool.go | sync.Pool — pool cục bộ theo từng P với fast path lock-free, dùng trong fmt, encoding/json |
| Work Stealing | runtime/proc.go | stealWork — scheduler goroutine lấy trộm từ queue chạy của P khác qua runqsteal/runqgrab |
| Free List | runtime/mfixalloc.go | fixalloc — allocator free-list kích thước cố định với node mlink xen vào |
| LRU Cache | groupcache lru/lru.go | Struct Cache với linked list hai chiều + hash map, do Brad Fitzpatrick viết |
| Consistent Hashing | groupcache consistenthash.go | Vòng hash với virtual node cho cache phân tán |
| Rate Limiter | x/time/rate | Rate limiter token bucket trong thư viện chuẩn mở rộng |
| Semaphore | x/sync/semaphore | Weighted semaphore — errgroup dùng nội bộ để giới hạn concurrency goroutine |
| Flyweight | sync/pool.go | sync.Pool như flyweight — Get() trả về instance đã cache thay vì cấp phát, Put() trả về để tái dùng |
| Arena Allocator | arena/arena.go | Arena allocator thử nghiệm — New[T]() cấp phát, Free() giải phóng tất cả một lúc, bỏ qua GC |
Cách chúng kết hợp: Lập lịch goroutine
Khi bạn khởi chạy go func(), nhiều pattern phối hợp để chạy hàng triệu goroutine trên vài thread OS:
go func() { ... }▼The runtime allocates goroutine stacks from a fixed-size allocator (fixalloc). No malloc/free per goroutine — just grab a node from the free list.
sync.Pool provides per-P local pools for temporary objects (like fmt buffers). Each P has a private pool → no lock contention.
The goroutine runs until it hits a preemption point (function call, channel op, or async preemption signal). Then the scheduler picks the next goroutine.
When a P's local run queue is empty, it steals goroutines from another P's queue. stealWork() grabs half the victim's queue in one batch, keeping all cores busy.
When goroutines need bounded concurrency (e.g., errgroup with limit), the weighted semaphore controls how many run at once.
Mô hình GMP (Goroutine, M thread, P processor) là chất kết dính: mỗi P sở hữu một run queue cục bộ, một allocator free-list và một shard sync.Pool. Work stealing chỉ kích hoạt khi P cạn việc. Thiết kế này nghĩa là hầu hết thao tác đều lock-free trên fast path, và tranh chấp chỉ xảy ra khi steal — vốn là trường hợp hiếm theo thiết kế.