How can you ensure that the following program only exists after the go-routine has executed -

package main

func expensiveOp() {
	sum := 0
	for i := range 1000000 {
		sum += i
	}
	println(sum)
}

func main() {
	go expensiveOp()
	println("main Function ended")
}

Screenshot 2024-10-21 at 12.31.53 PM.png

Solution - Add an unbuffered channel that blocks the receiver

package main

func expensiveOp(ch chan<- bool) {
	sum := 0
	for i := range 1000000 {
		sum += i
	}
	println(sum)
	ch <- true
}

func main() {
	ch := make(chan bool)
	go expensiveOp(ch)
	<-ch
	println("main Function ended")
}

Waitgroups

In Go, a WaitGroup is a synchronization primitive that allows you to wait for a collection of goroutines to finish executing.

Write a program that runs 5 different go routines and waits for all of them to exit before printing “done”

Ugly approach (without waitgroups)

package main

func expensiveOp(ch chan<- bool) {
	sum := 0
	for i := range 1000000 {
		sum += i
	}
	println(sum)
	ch <- true
}

func main() {
	ch1 := make(chan bool)
	go expensiveOp(ch1)

	ch2 := make(chan bool)
	go expensiveOp(ch2)

	ch3 := make(chan bool)
	go expensiveOp(ch3)

	ch4 := make(chan bool)
	go expensiveOp(ch4)

	ch5 := make(chan bool)
	go expensiveOp(ch5)

	<-ch1
	<-ch2
	<-ch3
	<-ch4
	<-ch5
	println("main Function ended")
}

Better approach (Using waitgroups)

package main

import "sync"

func expensiveOp() {
	sum := 0
	for i := range 1000000 {
		sum += i
	}
	println(sum)
}

func main() {
	var wg sync.WaitGroup
	for i := 0; i < 5; i++ {
		wg.Add(1)

		go func() {
			defer wg.Done()
			expensiveOp()
		}()
	}
	wg.Wait()
	println("main Function ended")
}

Assignment

Add a timeout to a go-routine so it gets ignored and execution continues if it takes more than 10 seconds