Go Goroutines

A goroutine is a lightweight thread managed by the Go runtime. Starting a goroutine costs very little memory — around 2KB compared to 1MB or more for a traditional OS thread. A single Go program can run thousands or even millions of goroutines at the same time.

Starting a Goroutine

Add the go keyword before a function call to run it as a goroutine.

package main

import (
    "fmt"
    "time"
)

func sayHello(name string) {
    fmt.Println("Hello from", name)
}

func main() {
    go sayHello("Alice") // runs concurrently
    go sayHello("Bob")   // runs concurrently

    time.Sleep(100 * time.Millisecond) // wait for goroutines to finish
    fmt.Println("Main function done")
}

Output (order may vary — goroutines run concurrently):

Hello from Alice
Hello from Bob
Main function done

Goroutine vs Normal Function Call

Normal call:         go keyword:
sayHello("Alice")    go sayHello("Alice")
       │                     │
       │                     └── runs in a new goroutine
       │                         main continues immediately
       ▼
main waits for it    main does NOT wait
to finish            for it to finish

Why the Sleep?

The main function is itself a goroutine. When it exits, the entire program stops — even if other goroutines are still running. The time.Sleep gives goroutines time to complete. The proper solution is to use a WaitGroup, which is covered in its own topic.

Goroutine with an Anonymous Function

package main

import (
    "fmt"
    "time"
)

func main() {
    for i := 1; i <= 3; i++ {
        go func(n int) {
            fmt.Println("Worker", n, "running")
        }(i)
    }

    time.Sleep(100 * time.Millisecond)
}

Output (order may vary):

Worker 1 running
Worker 3 running
Worker 2 running

Pass i as an argument to the anonymous function. Without the argument, all goroutines might capture the same final value of i.

Goroutine Memory Model

Go Runtime Scheduler

┌─────────────────────────────────────────┐
│               Go Program                │
│                                         │
│  goroutine 1 (main)                     │
│  goroutine 2 (go sayHello("Alice"))     │
│  goroutine 3 (go sayHello("Bob"))       │
│                                         │
│  Go Scheduler maps goroutines to OS     │
│  threads automatically                  │
└─────────────────────────────────────────┘

OS Threads (far fewer than goroutines)
Thread 1 ──► runs goroutines in turns
Thread 2 ──► runs goroutines in turns

Goroutines Are Cheap

FeatureGoroutineOS Thread
Initial stack size~2 KB~1 MB
Creation costVery lowHigh
Managed byGo runtimeOperating system
Practical limitMillionsThousands

Key Points

  • A goroutine is a lightweight concurrent task started with the go keyword
  • The Go runtime manages goroutines — not the operating system
  • Goroutines start with only ~2KB of stack, making them extremely cheap
  • The main function is itself a goroutine — when it exits, all goroutines stop
  • Pass loop variables as arguments to goroutine functions to avoid capture bugs
  • Use WaitGroups or channels to properly synchronize goroutines

Leave a Comment