Last active
August 29, 2015 14:26
-
-
Save kumikoda/731ea620d0f32050c479 to your computer and use it in GitHub Desktop.
Using go routines and channels to do some work
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"sync" | |
"time" | |
) | |
func main() { | |
// create the channel that all workers will listen on | |
tasks := make(chan string, 64) | |
// create a pool of workers | |
var wg sync.WaitGroup | |
for i := 0; i < 5; i++ { | |
// increment wait group | |
wg.Add(1) | |
// start the worker | |
// the tasks channel allows it to recieve work | |
// the wait group allows it to declare done | |
go worker(tasks, &wg) | |
} | |
// fill our task queue with some work | |
// if the channel is full, this will block | |
// and continue when its no longer full | |
test_ids := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"} | |
for _, id := range test_ids { | |
tasks <- id | |
} | |
// when all tasks have been sent out, we close this channel | |
// idle works will then quit | |
close(tasks) | |
// wait for all workers to quit | |
wg.Wait() | |
fmt.Println("main done") | |
} | |
func worker(tasks <-chan string, wg *sync.WaitGroup) { | |
// decrement wait group when worker exits | |
defer wg.Done() | |
// wait for tasks indefinitely | |
for { | |
task, ok := <-tasks | |
// not ok means channel has been closed | |
if !ok { | |
fmt.Println("worker done") | |
return | |
} | |
// take a task off the channel and work | |
time.Sleep(time.Second) | |
fmt.Println(task) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think it's more "idomatic" if you keep the
main()
as readable and straightforward as possible. So, instead of doing the for loop in main, you're probably better off breaking it out into its own function. In practice, themain
function gets abused and can become unwieldy pretty easily.Other than that, I think this is a pretty solid approach to worker pool/fan-out. It's a pretty popular topic. If you haven't already looked around, I found this thread insightful:
http://stackoverflow.com/questions/23837368/idiomatic-variable-size-worker-pool-in-go
And this example:
http://play.golang.org/p/VlEirPRk8V