What Are Goroutines?

A goroutine is a user-space thread—a lightweight execution context managed entirely by Go's runtime, not the OS kernel.

type g struct {
    stack       stack   // current stack bounds
    stackguard0 uintptr // for stack growth checks
    m           *m      // current M (OS thread) running this G
    sched       gobuf   // saved registers (PC, SP) for context switch
    atomicstatus uint32 // runnable, running, waiting, etc.
    // ... ~40 more fields
}

Each goroutine is just a struct (~2KB) containing:


CPU Registers: PC and SP

Every CPU has registers—tiny, ultra-fast storage locations. Two are critical for execution:

Register Name What It Holds
PC Program Counter Address of the next instruction to execute
SP Stack Pointer Address of the top of the current stack
Memory Layout (simplified)
─────────────────────────
│  Code (.text)         │  ← PC points somewhere here
─────────────────────────
│  ...                  │
─────────────────────────
│  Stack                │  ← SP points to top
│  ┌─────────────────┐  │
│  │ local var a     │  │
│  │ local var b     │  │
│  │ return address  │  │
│  └─────────────────┘  │
─────────────────────────

PC tells the CPU "where am I in the code?"

SP tells the CPU "where is my stack data?"


What Is a Context Switch?

When the scheduler switches from running Goroutine A to Goroutine B, it must:

  1. Save A's state (PC, SP, other registers) → so it can resume later
  2. Load B's saved state (PC, SP, other registers) → continue where B left off