concurrency
2w ago

How Goroutines Work Under the Hood

6 views • 0 upvotes

Memory Layout

code
┌─────────────────────────────────────┐
│         Goroutine Stack             │
│  (starts at ~2KB, grows dynamically)│
├─────────────────────────────────────┤
│         Function Call Frames        │
│  ┌─────────────────────────────┐   │
│  │ Frame N: Current Function   │   │
│  │  - Local variables          │   │
│  │  - Return address           │   │
│  │  - Function parameters      │   │
│  └─────────────────────────────┘   │
│  ┌─────────────────────────────┐   │
│  │ Frame N-1: Caller           │   │
│  └─────────────────────────────┘   │
│  ┌─────────────────────────────┐   │
│  │ Frame N-2: ...              │   │
│  └─────────────────────────────┘   │
├─────────────────────────────────────┤
│         Stack Pointer (SP)          │
│         Program Counter (PC)        │
│         Goroutine ID                │
│         Status (running/waiting)    │
└─────────────────────────────────────┘

Goroutine Lifecycle States

code
┌──────────┐
│ Created  │  (go keyword used)
└────┬─────┘
     │
     ▼
┌──────────┐
│ Runnable │  (waiting in queue)
└────┬─────┘
     │
     ▼
┌──────────┐     Blocking I/O
│ Running  │───────────────┐
└────┬─────┘               │
     │                     ▼
     │               ┌──────────┐
     │               │ Waiting  │
     │               └────┬─────┘
     │                    │
     │    Event Ready     │
     │◄───────────────────┘
     │
     │ Work Complete
     ▼
┌──────────┐
│   Dead   │
└──────────┘

Stack Growth Mechanism

Goroutine stacks are dynamically sized and grow/shrink as needed:

Initial State (2KB Stack)

code
Stack Start: 0x1000
Stack End:   0x1800 (2KB later)

┌──────────┐ 0x1000
│          │
│  Stack   │
│          │
│          │ ← Stack Pointer (0x1600)
│          │
└──────────┘ 0x1800

Stack Overflow Detected

code
Function prologue checks:
if SP - FrameSize < StackGuard {
    // Trigger stack growth
    morestack()
}

New Stack Allocated (4KB)

code
New Stack: 0x2000 - 0x3000

┌──────────┐ 0x2000
│          │
│          │
│   New    │
│  Stack   │ ← Copy old data here
│  (4KB)   │
│          │
│          │
└──────────┘ 0x3000

1. Allocate new stack (2x size)
2. Copy existing frames
3. Update all pointers
4. Switch to new stack
5. Continue execution
Key Points:
  • Check happens at every function call
  • Typically doubles in size (2KB → 4KB → 8KB → ...)
  • Old stack is garbage collected
  • Maximum stack size: 1GB on 64-bit systems

Was this helpful?

Difficulty & Status

medium
Lvl. 4
Community Verified
Progress: 11%
Answered by: shubham vyasPrev TopicNext Topic