Skip to main content

Program Start

The sequence of steps happening from the moment a Go program is launched until main.main function starts executing:

OS loader → _rt0_go (asm) → rt0_go (Go) → args + osinit + schedinit → runtime.main → run package inits → start main.main goroutine

1. Process startup (outside Go runtime)

  • The OS loader loads the binary into memory.
  • ELF/Mach-O/PE headers are parsed (depending on platform).
  • OS sets up the process image: stack, heap, environment, argc/argv, and entry point.

The entry point is not main.main — it's the Go runtime bootstrap symbol, usually _rt0_<arch>_<os>.

2. Runtime entry point (_rt0_go)

  • Defined in assembly (runtime/rt0_*.s) for each platform.
  • Responsibilities:
    • Initialize stack and registers.
    • Collect argc, argv, and envp from the OS.
    • Call into runtime.rt0_go (written in Go).

3. runtime.rt0_go

  • Sets up command-line arguments and environment variables.
  • Calls runtime.args() → stores argc and argv.
  • Calls runtime.osinit() → initializes OS-specific parts (thread-local storage, signal stack, etc).
  • Calls runtime.schedinit() → initializes the scheduler and global runtime state.

4. Scheduler initialization (schedinit)

  • Sets up:
    • G0: the scheduler goroutine (special stack, runs runtime code).
    • M0: the initial machine (thread) bound to G0.
    • P's: processors (number = GOMAXPROCS, default = # of CPUs).

At this point, the runtime can schedule goroutines, but none exist yet except G0.

5. Package initialization

  • Runtime calls runtime.main().
  • Inside runtime.main:
    • It creates the first real goroutine, which runs main.main (the program).
    • Before main.main, it executes:
      • All init functions in the imported packages (topological order of imports).
      • The init function in main package (if present).

init functions run sequentially, not concurrently.

6. Handing control to the program

  • After all init functions complete, the scheduler runs the goroutine for main.main.
  • The program begins.

At this point:

  • The scheduler is live.
  • The garbage collector is initialized.
  • The network poller and timer system are ready.
  • Runtime services like panic handling, defer stack, type system, etc. are fully operational.