Go Goroutines

Goroutines

A goroutine provides concurrency in Go. Goroutines are lightweight and can run concurrent work efficiently.

The following example starts funcA() as a goroutine with go while the main function continues its own work.

package main

import (
	"fmt"
	"time"
)

func funcA() {
	for i := 0; i < 10; i++ {
		fmt.Print("A")
		time.Sleep(10 * time.Millisecond)
	}
}

func main() {
	go funcA()
	for i := 0; i < 10; i++ {
		fmt.Print("M")
		time.Sleep(20 * time.Millisecond)
	}
}

Output:

MAAMAAAMAAMAAMAMMMMM

The next example uses a channel to wait for a goroutine to finish. chan declares a channel type, and <- sends or receives a message through a channel.

package main

import (
	"fmt"
	"time"
)

func funcA(chA chan<- string) {
	time.Sleep(3 * time.Second)
	chA <- "Finished" // send a message to the channel
}

func main() {
	chA := make(chan string) // create a channel
	defer close(chA)         // close it after use
	go funcA(chA)            // start the goroutine
	msg := <-chA             // receive a message from the channel
	fmt.Println(msg)
}

Output:

Finished

The following example uses select to wait for both funcA() and funcB().

package main

import (
	"fmt"
	"time"
)

func funcA(chA chan<- string) {
	time.Sleep(1 * time.Second)
	chA <- "funcA Finished"
}

func funcB(chB chan<- string) {
	time.Sleep(2 * time.Second)
	chB <- "funcB Finished"
}

func main() {
	chA := make(chan string)
	chB := make(chan string)
	defer close(chA)
	defer close(chB)
	finflagA := false
	finflagB := false
	go funcA(chA)
	go funcB(chB)
	for {
		select {
		case msg := <-chA:
			finflagA = true
			fmt.Println(msg)
		case msg := <-chB:
			finflagB = true
			fmt.Println(msg)
		}
		if finflagA && finflagB {
			break
		}
	}
}

Output:

funcA Finished
funcB Finished