Go by Example: Stateful Goroutines

A stateful Goroutine is a Goroutine that retains its state across multiple function invocations, allowing it to persist data between function calls. In Go, stateful Goroutines are implemented by passing data to a Goroutine as an argument and then accessing that data within the Goroutine.

Here’s an example of using stateful Goroutines in Go:

package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

func printRandomNumbers(wg *sync.WaitGroup, id int) {
	defer wg.Done()

	rand.Seed(time.Now().UnixNano())
	for i := 0; i < 10; i++ {
		fmt.Println("Goroutine", id, "generated random number", rand.Intn(100))
		time.Sleep(time.Second)
	}
}

func main() {
	var wg sync.WaitGroup

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go printRandomNumbers(&wg, i)
	}

	wg.Wait()
	fmt.Println("All Goroutines complete.")
}

In this example, the printRandomNumbers function generates and prints random numbers. The function is executed as a Goroutine and is passed the sync.WaitGroup and a unique id as arguments. The unique id argument is used to distinguish between Goroutines and the WaitGroup is used to wait for all Goroutines to complete. The state of the Goroutine is persisted between function calls, allowing it to generate and print random numbers 10 times. The use of stateful Goroutines allows you to maintain and persist data across multiple function invocations, making it easier to implement complex algorithms and patterns in concurrent programming.

Here’s another example of using stateful Goroutines in Go:

package main

import (
	"fmt"
	"sync"
)

func sum(a []int, c chan int) {
	total := 0
	for _, v := range a {
		total += v
	}
	c <- total
}

func main() {
	a := []int{7, 2, 8, -9, 4, 0}

	c := make(chan int)
	var wg sync.WaitGroup

	for i := 0; i < len(a); i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			sum(a[:i+1], c)
		}(i)
	}

	go func() {
		wg.Wait()
		close(c)
	}()

	for result := range c {
		fmt.Println(result)
	}
}

In this example, the sum function calculates the sum of an integer slice. The function is executed as a Goroutine and is passed an integer slice a and a channel c. The Goroutine writes the sum of the integer slice to the channel. The main function launches multiple Goroutines, each of which calculates the sum of a sub-slice of a and writes the result to the channel. The main function waits for all Goroutines to complete using a WaitGroup and then closes the channel. The main function reads the results from the channel and prints them to the console. The use of stateful Goroutines allows you to perform multiple calculations in parallel and communicate the results to the main Goroutine.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *