Description

A Goroutine is a lightweight, independently executing function managed by the Go runtime. It is the fundamental unit of concurrency in the Go programming language (Golang) and allows developers to run multiple tasks simultaneously, without the complexity of manual thread management.

Unlike traditional threads, goroutines are cheap to create, share the same address space, and are scheduled cooperatively by the Go runtime using a user-space scheduler.

Key Features

FeatureDescription
Lightweight ThreadsThousands of goroutines can be run simultaneously with minimal overhead
Automatic SchedulingGo runtime schedules goroutines, not the OS kernel
Shared Memory ModelCommunicate via channels, but variables exist in the same space
Non-blocking I/OEfficient use of system resources during network or file operations
Easy SyntaxUse go keyword to launch functions concurrently

Basic Syntax

func sayHello() {
    fmt.Println("Hello!")
}

func main() {
    go sayHello() // Executes in a separate goroutine
    time.Sleep(time.Second)
}

How It Works

  1. go keyword launches a goroutine.
  2. The function executes independently from the main goroutine.
  3. The Go scheduler maps goroutines onto a small pool of OS threads.
  4. Goroutines yield execution voluntarily during I/O or channel operations.
  5. Scheduler resumes them later using a cooperative scheduling model.

Real-Life Analogy

Imagine you’re organizing a group project. Instead of asking one person to do everything in order, you assign different people (goroutines) to handle specific parts in parallel. They work independently and report back via a shared board (channel).

Goroutines vs Threads

FeatureGoroutineThread
Memory~2KB stack, grows dynamically~1MB stack per thread
Startup CostExtremely lowRelatively high
CountCan create millionsUsually limited to thousands
SchedulingManaged by Go runtimeManaged by OS kernel
CommunicationUses channelsUses shared memory + synchronization

Channels: Communicating Between Goroutines

func worker(ch chan string) {
    ch <- "work done"
}

func main() {
    ch := make(chan string)
    go worker(ch)
    fmt.Println(<-ch)
}

Channels are typed pipes that connect concurrent goroutines.

Go Scheduler Model (M:N Scheduler)

Go uses an M:N scheduling model:

  • M = Number of OS threads
  • N = Number of goroutines
  • G = Goroutine structure
  • P = Processor context to execute goroutines

The scheduler maps many goroutines (G) to a smaller number of threads (M) using a number of logical processors (P).

Advanced Topics

Buffered Channels

ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3

Buffered channels allow storing data without immediate receiving.

Select Statement

Allows waiting on multiple channels:

select {
case msg := <-ch1:
    fmt.Println(msg)
case msg := <-ch2:
    fmt.Println(msg)
default:
    fmt.Println("no activity")
}

Goroutine Leak

Occurs when a goroutine is waiting on a channel that never sends data, causing a memory leak. Always ensure cleanup or use context cancellation.

Common Pitfalls

PitfallSolution
Missing go keywordOnly launches concurrently if prefixed with go
Data RaceUse channels or mutexes to avoid race conditions
DeadlocksAlways pair sends and receives, or use buffered channels
Goroutine LeakUse context.Context for lifecycle control
Blocking MainEnsure main goroutine waits (via WaitGroup, sleep, etc.)

Code Patterns

Launching Multiple Goroutines

for i := 0; i < 5; i++ {
    go func(n int) {
        fmt.Println(n)
    }(i)
}

Use function arguments to avoid variable capture issues.

WaitGroup for Synchronization

var wg sync.WaitGroup

wg.Add(1)
go func() {
    defer wg.Done()
    fmt.Println("done")
}()

wg.Wait()

Ensures main goroutine waits for others to finish.

Using context for Cancellation

ctx, cancel := context.WithCancel(context.Background())
go func(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
            // do work
        }
    }
}(ctx)

cancel() // signal cancellation

Performance and Scalability

Goroutines make Go extremely efficient for:

  • Network servers (e.g., thousands of concurrent connections)
  • Real-time applications
  • Parallel computations
  • Pipelines and stream processing

Tools for Debugging Goroutines

ToolPurpose
go run -raceDetects data races
pprofProfiles goroutines and memory
runtime.NumGoroutine()Returns active goroutine count

Related Concepts

ConceptRelationship
ChannelPrimary way to communicate between goroutines
WaitGroupSynchronizes completion of multiple goroutines
MutexProtects shared memory (alternative to channels)
TaskSimilar abstraction in .NET and Python
CoroutineGoroutines are a form of coroutine
SchedulerDetermines execution order of goroutines

Related Keywords

  • Channel
  • Concurrency
  • Cooperative Scheduling
  • Goroutine Leak
  • M:N Scheduler
  • Mutex
  • Race Condition
  • Runtime Scheduler
  • WaitGroup
  • Yield Point