http://play.golang.org/p/vhaKi5uVmm
package main
import \"fmt\"
var battle = make(chan string)
func warrior(name string, done chan struct{}) {
select
done
channel is used to receive notifications from warrior
method that indicates the worker is done processing. So the channel can be anything, for example:
func warrior(name string, done chan bool) {
select {
case opponent := <-battle:
fmt.Printf("%s beat %s\n", name, opponent)
case battle <- name:
// I lost :-(
}
done <- true
}
func main() {
done := make(chan bool)
langs := []string{"Go", "C", "C++", "Java", "Perl", "Python"}
for _, l := range langs { go warrior(l, done) }
for _ = range langs { <-done }
}
We declare done := make(chan bool)
as a channel that receives bool value, and send true
at the end of warrior
instead. This works! You can also define the done
channel to any other type, it won't matter.
1. So what is with the weird done <- struct{}{}
?
It is just another type that will be passed to channel. This is an empty struct, if you are familiar with the following:
type User struct {
Name string
Email string
}
struct{}
makes no difference except it contains no fields, and struct{}{}
is just an instance out of it. The best feature is it does not cost memory space!
2. for loop usage
We create 6 goroutines to run in the background with this line:
for _, l := range langs { go warrior(l, done) }
We use the for _ = range langs { <-done }
, because the main goroutine(where main function runs) does not wait for goroutins to finish.
If we does not include the last for line, chances are we see no outputs(because main goroutines quits before any child goroutines executes fmt.Printf
code, and when main goroutine quits, all child goroutines will quit with it, and will not have any chance to run anyway).
So we wait for all goroutines to finish(it runs to the end, and send a message to the done
channel), then exits. done
channel here is a blocked channel, which means <-done
will block here until a message is received from the channel.
We have 6 goroutines in the background, and use for loop, we wait until all goroutines send a message which means it finished running(because the done <-struct{}{}
is at the the end of function).