← Back to Go Course | Chapter 11: Concurrency | Lesson 1 of 8

Goroutines

A goroutine is like starting a new little worker inside your program who runs alongside everyone else at the same time, instead of making everyone wait their turn.

Starting a Goroutine

Prefixing a function call with the go keyword launches it as a goroutine, a lightweight, independently scheduled unit of concurrent execution managed by the Go runtime rather than the operating system directly.

Example: Starting a Goroutine

markup
package main

import (
	"fmt"
	"time"
)

func sayHello() {
	fmt.Println("hello from a goroutine")
}

func main() {
	go sayHello()
	time.Sleep(50 * time.Millisecond) // give the goroutine time to run
	fmt.Println("main finished")
}

main() Doesn't Wait

The program exits as soon as main() returns, regardless of whether any goroutines it launched have finished -- this is why real code needs explicit synchronization, not just a hope that things finish 'fast enough'.

Note: Without some form of synchronization, a program can exit before its goroutines finish -- always coordinate with channels or WaitGroup instead of Sleep in real code.

Example: main() Doesn't Wait

markup
package main

import "fmt"

func main() {
	done := make(chan bool)
	go func() {
		fmt.Println("goroutine work happening")
		done <- true
	}()
	<-done // waits until the goroutine signals completion
	fmt.Println("main continues only after goroutine finishes")
}

Many Lightweight Goroutines

Because goroutines start with a small, growable stack (just a few KB) rather than a full OS thread's overhead, a Go program can comfortably run thousands of them concurrently.

Example: Many Lightweight Goroutines

markup
package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(n int) {
			defer wg.Done()
			fmt.Println("worker", n, "done")
		}(i)
	}
	wg.Wait()
}
Common Mistakes
  1. Launching a goroutine and letting main() return before it finishes, silently killing it mid-work with no error.
  2. Assuming 'go func()' runs immediately and synchronously -- it's scheduled to run concurrently, with no guaranteed start order.
  3. Forgetting that goroutines sharing data without synchronization can race, corrupting shared state unpredictably.
Chapter Summary
  • The go keyword launches a function call as a new, concurrently running goroutine.
  • Goroutines are extremely lightweight compared to OS threads -- thousands can run at once.
  • The main goroutine doesn't wait for other goroutines automatically; the program exits when main() returns.
  • Coordinating goroutines typically requires channels or sync primitives like WaitGroup.
🔒

Chapter Quiz — Complete all 8 topics to unlock

0/8 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.