Concurrency: Channels - kyunghoj/golang GitHub Wiki
Channels
Channels provide a way for two goroutines to communicate with each other and synchronize their execution. Here is an example program using channels:
package main
import (
"fmt"
"time"
)
func pinger(c chan string) {
for i := 0; ; i++ {
c <- "ping"
}
}
func printer(c chan string) {
for {
msg := <- c
fmt.Println(msg)
time.Sleep(time.Second * 1)
}
}
func main() {
var c chan string = make(chan string)
go pinger(c)
go printer(c)
var input string
fmt.Scanln(&input)
}
Channel Direction
We can specify a direction on a channel type, thus restricting it to either sending or receiving. For example, pinger
's function signature can be changed to this:
func pinger(c chan<- string)
Now pinger
is only allowed to send to c
. Similarly, we can change printer
to this:
func printer(c<-chan string)
A channel that doesn't have these restrictions is known as bidirectional.
Select
select
picks the first channel that is ready and receives from it (or sends to it). If more than one of the channels are ready, then it randomly picks which one to receive from. If none of the channels are ready, the statement blocks until one becomes available.
The select
statement is often used to implement a timeout:
select {
case msg1 := <- c1:
fmt.Println("Message 1", msg1)
case msg2 := <- c2:
fmt.Println("Message 2", msg2)
case <- time.After(time.Second):
fmt.Println("timeout")
}
Buffered Channel
It's also possible to pass a second parameter to the make
function when creating a channel:
c := make(chan int, 1)
This creates a buffered channel with a capacity of 1. Normally, channels are synchronous; both sides of the channel will wait until the other side is ready. A buffered channel is asynchronous; sending or receiving a message will not wait unless the channel is already full, then sending will wait until there is room for at least one more int
.