Go - Channels
Updated at 2022-04-19 03:05
Channels can be viewed as a FIFO (first in, first out) message queues. Channels are used to transfer values, or more accurately, transfer ownerships of values, between goroutines.
You create channels with make
. The zero values of channel types is nil
.
c := make(chan int, 10)
// chan int = channel type (channel of integers here)
// 10 = value buffer capacity, can be omitted for unbuffered channels
A channel with zero capacity is called unbuffered channel and a channel with non-zero capacity is called buffered channel.
Common channel operations:
ch <- v // send value v to channel ch
v, ok = <-ch // receive value v, and "ok" becomes false if the channel is closed
cap(ch) // returns value buffer capacity
len(ch) // returns number of values currently in value buffer
close(ch) // closing a channel, closing nil or already closed channel will panic
close()
on anil
channel will panic.ch <- v
on anil
channel will block forever.v, ok = <-ch
on anil
channel will block forever.
You usually use channels with for
and select
statements:
for v = range ch {
// waits for `v` values until the channel is closed
}
select
is useful for listening multiple channels:
package main
import (
"fmt"
"time"
)
func main() {
greetings := make(chan string)
names := make(chan string)
go func() {
greetings <- "hello"
time.Sleep(1 * time.Second)
greetings <- "hi!"
time.Sleep(1 * time.Second)
close(greetings)
}()
go func() {
names <- "John"
time.Sleep(1 * time.Second)
names <- "Bob"
time.Sleep(2 * time.Second)
close(names)
}()
LOOP:
for {
select {
case g, ok := <-greetings:
if !ok {
break LOOP
}
fmt.Println(g)
case n, ok := <-names:
if !ok {
break LOOP
}
fmt.Println(n)
}
}
fmt.Println("End.")
}