Goroutines

2-minute read
Table of Contents

A goroutine is a lightweight thread of execution. We can use them to execute instructions concurrently. After defining the function, use the go keyword to tell Go to execute the function using the goroutine:

package main

import (
	"fmt"
	"time"
)

func countNumberOfAs(input string) {
	count := 0
	for i := range input {
		if string(input[i]) == "a" {
			count++
		}
	}
	fmt.Println(input, "has", count, "a's")
}

func main() {
	countNumberOfAs("What is up Harry?")
	go countNumberOfAs("How are you?")

	// go routine with anonymous function
	go func(message string) {
		fmt.Println("The message is:", message)
	}("Hello")

	// wait for a second
	time.Sleep(time.Second)
}
goroutine-simple.go
Copy

The use of time.Sleep is to ensure the program is running long enough for the goroutine to complete. We ask the program to wait for a second.

Wait groups

The correct way to handle is to use a WaitGroup from the sync package:

package main

import (
	"fmt"
	"sync"
)

func countNumberOfAs(taskNum int, input string) {
	count := 0
	for i := range input {
		if string(input[i]) == "a" {
			count++
		}
	}
	fmt.Printf("task %d: '%s' has %d a's\n", taskNum, input, count)
}

func main() {
	statements := []string{
		"What is up Harry?",
		"How are you?",
		"What is up Harry?",
		"How are you?",
		"What is up Harry?",
		"How are you?",
		"What is up Harry?",
		"How are you?",
		"What is up Harry?",
		"How are you?",
		"What is up Harry?",
		"How are you?",
	}

	var wg sync.WaitGroup

	for i := range statements {
		// queue functions into the wait group
		wg.Go(func() {
			countNumberOfAs(i, statements[i])
		})
	}

	// wait for all goroutines in the wait group to finish
	wg.Wait()

	// indicate end of program
	fmt.Println("program done")
}
goroutine-waitgroup.go
Copy

The wg.Go function accepts a function to be executed in the goroutine. All of the goroutines will finish execution before the program continues after wg.Wait(). Run the program multiple times and notice the output each time. The “program done” statement will always be printed at the end because of wg.Wait() whereas the order in which the tasks executed in the goroutines can change.

If a wait group is to be explicitly passed into a function, we must pass by reference (using a pointer).

Support us via BuyMeACoffee