publish closing-channels and range-over-channels
This commit is contained in:
parent
e6a3c56d77
commit
dc35e6c751
@ -32,7 +32,8 @@ Channel Directions
|
|||||||
Select
|
Select
|
||||||
Timeouts
|
Timeouts
|
||||||
Non-Blocking Channel Operations
|
Non-Blocking Channel Operations
|
||||||
# Closing Channels
|
Closing Channels
|
||||||
|
Range over Channels
|
||||||
# Scatter Gather
|
# Scatter Gather
|
||||||
# Rate Limiting
|
# Rate Limiting
|
||||||
# Worker Pools
|
# Worker Pools
|
||||||
|
@ -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
|
package main
|
||||||
|
|
||||||
import "fmt"
|
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() {
|
func main() {
|
||||||
jobs := make(chan bool, 5)
|
jobs := make(chan int, 5)
|
||||||
done := make(chan bool)
|
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() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
_, more := <-jobs
|
j, more := <-jobs
|
||||||
if more {
|
if more {
|
||||||
fmt.Println("received job")
|
fmt.Println("received job", j)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("received all")
|
fmt.Println("received all jobs")
|
||||||
done <- true
|
done <- true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for i := 0; i < 5; i++ {
|
// This sends 3 jobs to the worker over the `jobs`
|
||||||
jobs <- false
|
// channel, then closes it.
|
||||||
fmt.Println("sent job")
|
for j := 1; j <= 3; j++ {
|
||||||
|
jobs <- j
|
||||||
|
fmt.Println("sent job", j)
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
|
||||||
close(jobs)
|
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
|
<-done
|
||||||
}
|
}
|
||||||
|
12
examples/closing-channels/closing-channels.sh
Normal file
12
examples/closing-channels/closing-channels.sh
Normal 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.
|
26
examples/range-over-channels/range-over-channels.go
Normal file
26
examples/range-over-channels/range-over-channels.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
7
examples/range-over-channels/range-over-channels.sh
Normal file
7
examples/range-over-channels/range-over-channels.sh
Normal 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.
|
Loading…
x
Reference in New Issue
Block a user