Concurrent Prime Finder with Go: Goroutines and Channels
33 views
Exercise: Concurrent Prime Number Finder
In this exercise, you will create a Go program that finds prime numbers concurrently. The program will use multiple goroutines to check for prime numbers in a given range and will report the primes found.
Requirements
- Concurrency: Use goroutines to split the work of checking numbers in the given range.
- Channels: Use channels to collect results from the goroutines.
- Synchronization: Ensure the main goroutine waits for all worker goroutines to finish before exiting.
- Prime Checking: Implement an efficient prime checking function.
Steps
- Set Up Goroutines: Create a function that starts multiple worker goroutines.
- Use Channels: Use a channel to send results from the worker goroutines to the main goroutine.
- WaitGroup: Use a
sync.WaitGroupto wait for all worker goroutines to finish. - Prime Checking Function: Write an efficient function to check if a number is prime.
- Combine Results: Collect and print the prime numbers found by the worker goroutines.
Here’s a possible structure for your program:
package main
import (
"fmt"
"math"
"sync"
)
// isPrime checks if a number is a prime
func isPrime(n int) bool {
if n <= 1 {
return false
}
if n == 2 {
return true
}
if n%2 == 0 {
return false
}
sqrt := int(math.Sqrt(float64(n)))
for i := 3; i <= sqrt; i += 2 {
if n%i == 0 {
return false
}
}
return true
}
// worker function to check a range of numbers for primes
func worker(start, end int, wg *sync.WaitGroup, primes chan<- int) {
defer wg.Done()
for num := start; num <= end; num++ {
if isPrime(num) {
primes <- num
}
}
}
func main() {
var start, end, numWorkers int
fmt.Printf("Enter start of the range: ")
fmt.Scan(&start)
fmt.Printf("Enter end of the range: ")
fmt.Scan(&end)
fmt.Printf("Enter number of workers: ")
fmt.Scan(&numWorkers)
primes := make(chan int, (end-start)/2) // Buffer size can be optimized.
var wg sync.WaitGroup
step := (end - start + 1) / numWorkers
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
workerStart := start + i*step
workerEnd := workerStart + step - 1
if i == numWorkers-1 {
workerEnd = end
}
worker(workerStart, workerEnd, &wg, primes)
}(i)
}
go func() {
wg.Wait()
close(primes)
}()
fmt.Println("Prime numbers in the range:")
for prime := range primes {
fmt.Println(prime)
}
}
What to Do:
- Ensure the code compiles and runs correctly.
- Experiment with different ranges and worker counts to see the effects.
- Think about potential improvements like more optimized buffer sizes or enhanced prime-checking