← 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.
Syntax
go
go functionName(args)

go func() {
    // body
}()

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
// Every Go file belongs to a package; main builds an executable
package main

// Import the packages this program uses
import (
	"fmt"
	"sync"
)

// main is where the program starts running
func main() {
	// Declare wg with the zero value of its type
	var wg sync.WaitGroup
	// Loop: repeat while the condition holds
	for i := 0; i < 5; i++ {
		wg.Add(1)
		// Start this call in a new goroutine (runs concurrently)
		go func(n int) {
			// defer runs this call when the surrounding function returns
			defer wg.Done()
			// Print the values followed by a newline
			fmt.Println("worker", n, "done")
		}(i)
	}
	wg.Wait()
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
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.