Skip to content

Instantly share code, notes, and snippets.

@rapando
Last active April 20, 2021 10:15
Show Gist options
  • Save rapando/eb8676172a52c6d3669c62c0947dafbc to your computer and use it in GitHub Desktop.
Save rapando/eb8676172a52c6d3669c62c0947dafbc to your computer and use it in GitHub Desktop.
package main
import (
"log"
"sync"
"time"
)
func main() {
// task - multiply each number by 2 then print out the results
var msisdns = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
log.Printf("msisdns : %v\n", msisdns)
start := time.Now()
implementation1(msisdns)
log.Printf("Implementation 1 took %v", time.Since(start))
start2 := time.Now()
implementation2(msisdns)
log.Printf("Implementation 2 took %v", time.Since(start2))
start3 := time.Now()
implementation3(msisdns)
log.Printf("Implementation 3 took %v", time.Since(start3))
}
func implementation1(msisdns []int) {
// create 10 goroutines to work on each number
log.Printf("Implementation One :: using goroutines and channels")
var stopChan = make(chan int, len(msisdns))
for _, msisdn := range msisdns {
go multiplyByTwoImplementation1(msisdn, stopChan)
}
var answer int
// the point is to loop 10 times
for _ = range msisdns {
answer = <-stopChan
log.Println("The answer is", answer)
}
}
func multiplyByTwoImplementation1(msisdn int, stopChan chan<- int) {
answer := multiplyBy2(msisdn)
stopChan <- answer
}
func implementation2(msisdns []int) {
// this one uses waitgroups
log.Println("\n\nImplementation 2 : waitgroups")
var wg sync.WaitGroup
for _, msisdn := range msisdns {
wg.Add(1)
go multiplyByTwoImplementation2(&wg, msisdn)
}
wg.Wait()
}
func multiplyByTwoImplementation2(wg *sync.WaitGroup, msisdn int) {
defer wg.Done()
answer := multiplyBy2(msisdn)
log.Printf("%d * 2 = %d\n", msisdn, answer)
}
func implementation3(msisdns []int) {
log.Println("\n\nImplementation 3 : Using worker pools")
// 1. Create the channels: jobs and results. the size of each should be how
// many data components you have
size := len(msisdns)
var jobs = make(chan int, size)
var results = make(chan int, size)
// 2. Read from the array of data into the jobs channel
for _, msisdn := range msisdns {
jobs <- msisdn
}
// 3. Create goroutines and provide them with the jobs and results channels
// Note that steps 2 and 3 can be interchanged but it makes sense writing
// them in this order
noOfGoroutines := 10 // 0 < noOfGoroutines <= size
for i := 0; i < noOfGoroutines; i++ {
go multiplyByTwoImplementation3(i, jobs, results)
}
// 4. Read the results (like in implementation 1)
var answer int
for i := 0; i < len(msisdns); i++ {
answer = <-results
log.Println("The answer is", answer)
}
}
// we are reading from jobs hence { jobs [<- chan int] }
// we are writing to results hence { results [chan <- int] }
func multiplyByTwoImplementation3(i int, jobs <-chan int, results chan<- int) {
for j := range jobs {
answer := multiplyBy2(j)
log.Printf("Worker [%d] working on %d", i, j)
results <- answer
}
}
func multiplyBy2(i int) int {
time.Sleep(time.Second * 2)
return i * 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment