Golang / GoLang Concurrency Mastery Interview Questions
What is the lock-held-during-I/O anti-pattern and how do you fix it?
Holding a mutex while performing I/O (network calls, disk reads) serialises all goroutines that need that lock for the entire I/O duration. This collapses concurrency to near-zero throughput — one of the most common Go performance mistakes.
// ANTI-PATTERN: lock held during HTTP call type Cache struct { mu sync.Mutex items map[string]string } func (c *Cache) GetBad(key string) string { c.mu.Lock() defer c.mu.Unlock() if v, ok := c.items[key]; ok { return v } // LOCK HELD DURING NETWORK CALL â all other callers serialise here! resp, _ := http.Get("https://api.example.com/" + key) body, _ := io.ReadAll(resp.Body) c.items[key] = string(body) return c.items[key] } // CORRECT: release lock before I/O, re-acquire after func (c *Cache) GetGood(key string) string { // Phase 1: fast check under lock c.mu.Lock() if v, ok := c.items[key]; ok { c.mu.Unlock() return v } c.mu.Unlock() // Phase 2: expensive I/O WITHOUT the lock resp, _ := http.Get("https://api.example.com/" + key) body, _ := io.ReadAll(resp.Body) result := string(body) // Phase 3: store result under lock c.mu.Lock() c.items[key] = result c.mu.Unlock() return result } // Even better: use singleflight to deduplicate concurrent fetches for the same key
More Related questions...