publish more advanced channel examples
This commit is contained in:
parent
86867c9cff
commit
b044506449
@ -27,15 +27,15 @@ Recursion
|
||||
Goroutines
|
||||
Channels
|
||||
Channel Buffering
|
||||
# Channel Directions
|
||||
# Synchronization
|
||||
Channel Synchronization
|
||||
Channel Directions
|
||||
Select
|
||||
Timeouts
|
||||
Non-Blocking Channel Operations
|
||||
# Closing Channels
|
||||
# Scatter Gather
|
||||
# Rate Limiting
|
||||
# Worker Pools
|
||||
# Non-Blocking Channel Operations
|
||||
# Closing Channels
|
||||
Timers
|
||||
Tickers
|
||||
# State Goroutine
|
||||
|
@ -1,35 +1,30 @@
|
||||
// When using channels as function parameters, you can
|
||||
// specify if a channel is meant to only send or receive
|
||||
// values. This specificity further increases the
|
||||
// type-safety of the program.
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func pinger(pings chan<- string) {
|
||||
for i := 0; i <= 10; i++ {
|
||||
pings <- "ping"
|
||||
}
|
||||
// This `ping` function only accepts a channel for sending
|
||||
// values. It would be a compile-time error to try to
|
||||
// receive on this channel.
|
||||
func ping(pings chan<- string, msg string) {
|
||||
pings <- msg
|
||||
}
|
||||
|
||||
func ponger(pings <-chan string, pongs chan<- string) {
|
||||
for {
|
||||
<-pings
|
||||
pongs <- "pong"
|
||||
}
|
||||
}
|
||||
|
||||
func printer(pongs <-chan string) {
|
||||
for {
|
||||
msg := <-pongs
|
||||
fmt.Println(msg)
|
||||
}
|
||||
// The `pong` function accepts one channel for receives
|
||||
// (`pings`) and a second for sends (`pongs`)
|
||||
func pong(pings <-chan string, pongs chan<- string) {
|
||||
msg := <-pings
|
||||
pongs <- msg
|
||||
}
|
||||
|
||||
func main() {
|
||||
var pings chan string = make(chan string)
|
||||
var pongs chan string = make(chan string)
|
||||
|
||||
go pinger(pings)
|
||||
go ponger(pings, pongs)
|
||||
go printer(pongs)
|
||||
|
||||
var input string
|
||||
fmt.Scanln(&input)
|
||||
pings := make(chan string, 1)
|
||||
pongs := make(chan string, 1)
|
||||
ping(pings, "passed message")
|
||||
pong(pings, pongs)
|
||||
fmt.Println(<-pongs)
|
||||
}
|
||||
|
2
examples/channel-directions/channel-directions.sh
Normal file
2
examples/channel-directions/channel-directions.sh
Normal file
@ -0,0 +1,2 @@
|
||||
$ go run channel-directions.go
|
||||
passed message
|
32
examples/channel-synchronization/channel-synchronization.go
Normal file
32
examples/channel-synchronization/channel-synchronization.go
Normal file
@ -0,0 +1,32 @@
|
||||
// We can use channels to synchronize execution
|
||||
// across goroutines. Here's an example of using a
|
||||
// blocking receive to wait for a goroutine to finish.
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "time"
|
||||
|
||||
// This is the function we'll run in a goroutine. The
|
||||
// `done` channel will be used to notify another
|
||||
// goroutine that this function's work is done.
|
||||
func worker(done chan bool) {
|
||||
fmt.Print("working...")
|
||||
time.Sleep(time.Second)
|
||||
fmt.Println(" done")
|
||||
|
||||
// Send a value to notify that we're done.
|
||||
done <- true
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
// Start a worker goroutine, giving it the channel to
|
||||
// notify on.
|
||||
done := make(chan bool, 1)
|
||||
go worker(done)
|
||||
|
||||
// Block until we receive a notification from the
|
||||
// worker on the channel.
|
||||
<-done
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
$ go run channel-synchronization.go
|
||||
working...done
|
||||
|
||||
# If you removed the `<- done` line from this program, the
|
||||
# program would exit before the `worker` even
|
||||
# started.
|
@ -1,3 +1,8 @@
|
||||
// Basic sends and receives on channels are blocking.
|
||||
// However, we can use `select` with a `default` clause to
|
||||
// implement _non-blocking_ sends, receives, and even
|
||||
// non-blocking multi-way `select`s.
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
@ -6,24 +11,30 @@ func main() {
|
||||
messages := make(chan string)
|
||||
signals := make(chan bool)
|
||||
|
||||
// Non-blocking receive.
|
||||
// Here's a non-blocking receive. If a value is
|
||||
// available on `messages` then `select` will take
|
||||
// the `<-messages` `case` with that value. If not
|
||||
// it will immediately take the `default` case.
|
||||
select {
|
||||
case msg := <-messages:
|
||||
fmt.Println("received message", msg)
|
||||
default:
|
||||
fmt.Println("no messages received")
|
||||
fmt.Println("no message received")
|
||||
}
|
||||
|
||||
// Non-blocking send.
|
||||
// A non-blocking send works similarly.
|
||||
msg := "hi"
|
||||
select {
|
||||
case messages <- msg:
|
||||
fmt.Println("sent message", msg)
|
||||
default:
|
||||
fmt.Println("no messages sent")
|
||||
fmt.Println("no message sent")
|
||||
}
|
||||
|
||||
// Non-blocking multi-way select.
|
||||
// We can use multiple `case`s above the `default`
|
||||
// clause to implement a multi-way non-blocking
|
||||
// select. Here we attempt non-blocking receives
|
||||
// on both `messages` and `signals`.
|
||||
select {
|
||||
case msg := <-messages:
|
||||
fmt.Println("received message", msg)
|
||||
|
@ -0,0 +1,4 @@
|
||||
$ go run non-blocking-channel-operations.go
|
||||
no message received
|
||||
no message sent
|
||||
no activity
|
@ -1,30 +0,0 @@
|
||||
// We can use channels to synchronize execution
|
||||
// accross goroutines. Here's an example of waiting
|
||||
// for another goroutine to finish.
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "time"
|
||||
|
||||
// The `done` channel will be used for
|
||||
// synchronization.
|
||||
func worker(done chan<- bool) {
|
||||
fmt.Print("Working...")
|
||||
time.Sleep(time.Second)
|
||||
fmt.Println(" done")
|
||||
|
||||
// Send a value to notify that the work is done.
|
||||
done <- true
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Start a worker goroutine, give it the channel to
|
||||
// notify on.
|
||||
done := make(chan bool, 1)
|
||||
go worker(done)
|
||||
|
||||
// Block until we can receive a value from the worker
|
||||
// over the channel.
|
||||
<-done
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
$ go run synchronization.go
|
||||
Working... done
|
||||
|
||||
# If you commented out the `<- done` line, the
|
||||
# program would exit before the `worker` even
|
||||
# started.
|
Loading…
x
Reference in New Issue
Block a user