Skip to content

Instantly share code, notes, and snippets.

@klrkdekira
Created August 20, 2016 15:20
Show Gist options
  • Save klrkdekira/6edb0a66a618532b9c411f388fed7b42 to your computer and use it in GitHub Desktop.
Save klrkdekira/6edb0a66a618532b9c411f388fed7b42 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
// Best practice, declare the last routine first
// the print (io) worker
outputChan := make(chan string, 10)
// goroutine with signal
printDone := printWorker(outputChan)
// start n fizzbuzzWorker
// n = number of system cores
coreCount := runtime.NumCPU()
// bootstrap the waitgroup
wg := &sync.WaitGroup{}
wg.Add(coreCount)
inputChan := make(chan int, 10)
for i := 0; i < coreCount; i++ {
go fizzbuzzWorker(inputChan, outputChan, wg)
}
for i := 1; i <= 100; i++ {
inputChan <- i
}
// Always remember to close channel to avoid deadlock
close(inputChan)
// Block until all executed
wg.Wait()
// Close because no more new message to output channel
close(outputChan)
// Wait signal from printWorker
<-printDone
}
func printWorker(in <-chan string) <-chan bool {
signal := make(chan bool)
go func() {
// Iterate by range only works with buffered channel
for msg := range in {
fmt.Println(msg)
}
// Remember, close is a message too, remember to capture it
close(signal)
}()
return signal
}
func fizzbuzzWorker(in <-chan int, out chan<- string, wg *sync.WaitGroup) {
// This works across both buffered and unbuffered channel
for {
i, more := <-in
// Check if this is the close signal
if !more {
break
}
msg := fmt.Sprintf("%03d - ", i)
if i%3 == 0 {
msg += "fizz"
}
if i%5 == 0 {
msg += "buzz"
}
out <- msg
}
wg.Done()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment