mdawar.dev

A blog about programming, Web development, Open Source, Linux and DevOps.

Go - Goroutines

A goroutine is a lightweight thread managed by the Go runtime.

Create a Goroutine

When a program starts a main goroutine calls the main function, new goroutines are created with the go statement.

go
// Regular function call.
// Call the function `f` and wait for it to return.
f()

// Create a new goroutine that calls `f` and don't wait for it to return.
// When the function terminates, its goroutine also terminates and the values
// returned by the function are ignored.
go f()

// The function value and parameters are evaluated in the calling goroutine
// and the execution of the function happens in a new goroutine.
go doSomething(x, y, z)

// Create a goroutine with a closure (anonymous function).
go func() {
  // Code to execute concurrently
}()

Goroutines run in the same address space, so access to shared memory must be synchronized.

Wait for Goroutines

A sync.WaitGroup can be used to wait for goroutines to complete their work.

go
import "sync"

// Declare a `WaitGroup` variable.
// No need to initialize it, the zero value is useful.
var wg sync.WaitGroup

// The main goroutine calls `Add` to set the number of goroutines to wait for.
wg.Add(1)

// Each goroutine calls `Done` when finished.
go func() {
  defer wg.Done()
  //...
}()

// Block until all the goroutines have finished.
wg.Wait()

Example:

go
package main

import (
  "fmt"
  "sync"
)

func main() {
  var wg sync.WaitGroup

  // Create 10 goroutines and wait for them to complete.
  for i := 0; i < 10; i++ {
    // The `Add` method is called before creating the goroutine.
    wg.Add(1) // Increment the WaitGroup counter

    go func(i int) {
      defer wg.Done() // Decrement the counter when the goroutine completes

      fmt.Println(i)
    }(i)
  }

  // Wait for all the goroutines to complete.
  wg.Wait() // Block until the counter becomes 0
}