publish closing-channels and range-over-channels

This commit is contained in:
Mark McGranaghan 2012-10-18 08:47:44 -07:00
parent e6a3c56d77
commit dc35e6c751
5 changed files with 75 additions and 12 deletions

View File

@ -32,7 +32,8 @@ Channel Directions
Select
Timeouts
Non-Blocking Channel Operations
# Closing Channels
Closing Channels
Range over Channels
# Scatter Gather
# Rate Limiting
# Worker Pools

View File

@ -1,33 +1,50 @@
// _Closing_ a channel indicates that no more values
// will be sent on it. This can be useful to communicate
// completion to the channel's receivers.
package main
import "fmt"
import "time"
// In this example we'll use a `jobs` channel to
// communicate work to be done from the `main()` goroutine
// to a worker goroutine. When we have no more jobs for
// the worker we'll `close` the `jobs` channel.
func main() {
jobs := make(chan bool, 5)
jobs := make(chan int, 5)
done := make(chan bool)
// Here's the worker goroutine. It repeatedly receives
// from `jobs` with `j, more := <-jobs`. In this
// special 2-value form of receive, the `more` value
// will be `false` if `jobs` has been `close`d and all
// values in the channel have already been received.
// We use this to notify on `done` when we've worked
// all our jobs.
go func() {
for {
_, more := <-jobs
j, more := <-jobs
if more {
fmt.Println("received job")
fmt.Println("received job", j)
} else {
fmt.Println("received all")
fmt.Println("received all jobs")
done <- true
return
}
}
}()
for i := 0; i < 5; i++ {
jobs <- false
fmt.Println("sent job")
// This sends 3 jobs to the worker over the `jobs`
// channel, then closes it.
for j := 1; j <= 3; j++ {
jobs <- j
fmt.Println("sent job", j)
}
time.Sleep(100 * time.Millisecond)
close(jobs)
fmt.Println("sent all")
fmt.Println("sent all jobs")
// We await the worker using the
// [synchronization](channel-synchronization) approach
// we saw earlier.
<-done
}

View File

@ -0,0 +1,12 @@
$ go run closing-channels.go
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs
# The idea of closed channels leads naturally to our next
# example: `range` over channels.

View File

@ -0,0 +1,26 @@
// In a [previous](range) example we saw how `for` and
// `range` provide iteration over basic data structures.
// We can also use this syntax to iterate over
// values received from a channel.
package main
import "fmt"
func main() {
// We'll iterate over 2 values in the `queue` channel.
queue := make(chan string, 2)
queue <- "one"
queue <- "two"
close(queue)
// This `range` iterates over each element as it's
// received from `queue`. Because we `close`d the
// channel above, the iteration terminates after
// receiving the 2 elements. If we didn't `close` it
// we'd block on a 3rd receive in the loop.
for elem := range queue {
fmt.Println(elem)
}
}

View File

@ -0,0 +1,7 @@
$ go run range-over-channels.go
one
two
# This example also showed that it's possible to close
# a non-empty channel but still have the remaining
# values be received.