Go channel
last modified April 11, 2024
In this article we show how to work with channels in Golang.
$ go version go version go1.22.2 linux/amd64
We use Go version 1.22.2.
Goroutine is a lightweight execution thread. It is a function that runs concurrently alongside other running code.
Channels are used to communicate between goroutines.
Channel functions and operators
In this section, we cover functions and operators related to channels.
c := make(chan int)
A channel is created with the make
function and the
chan
keyword. A channel is given a type.
The <-
operator is used to read a channel and write to a
channel.
c <- v
This line writes a value to a channel.
<- c
This line reads a value from a channel.
close(c)
A channel is closed with the close
function.
for e := range(c) { fmt.Println(e) }
We can iterate over values from a channel with range
.
len(c)
The len
function returns the number of elements which have already
been sent successfully to the channel but haven't been taken out yet.
Unidirectional channels
By default, the channels are bidirectional. They can be both used to send and receive data.
rc chan<- int
Placing the arrow operator on the right side of the chan
keyword,
we create a receive-only channel.
wc <-chan int
Placing the arrow operator on the left side of the chan
keyword,
we create a send-only channel.
Go channel simple example
The following is a simple example that uses a channel.
package main import "fmt" func main() { c := make(chan string) go func() { c <- "an old falcon" }() msg := <-c fmt.Println(msg) }
In the program, we have two goroutines. One is created with the go
keyword; the main function is also a goroutine.
c := make(chan string)
We create a channel of type string.
go func() { c <- "an old falcon" }()
Inside an anonymous goroutine, we send a string message to the channel.
msg := <-c
Inside the main goroutine, we read the value from the channel.
$ go run main.go an old falcon
Go channel deadlock
A channel deadlock happens when the code is blocked while using a channel. A channel is blocked when we try to read from an open and empty channel or try to write to an open and full channel.
package main import "fmt" func main() { c := make(chan string) c <- "an old falcon" msg := <-c fmt.Println(msg) }
This program ends in a deadlock.
c <- "an old falcon"
We write a value to a channel. The channel blocks and waits until it is emptied. Therefore, the line that reads from the channel and empties it is not reached. This situation leads to a deadlock.
$ go run main.go fatal error: all goroutines are asleep - deadlock! ...
Go channel range
We can use the range keyword to go over the data sent to a channel.
package main import ( "fmt" "time" ) func main() { c := make(chan string) go hello("Martin", c) for msg := range c { fmt.Println(msg) } } func hello(name string, c chan string) { for i := 0; i < 5; i++ { msg := fmt.Sprintf("Hello %s!", name) c <- msg time.Sleep(time.Millisecond * 500) } close(c) }
In the program, we send five messages to a channel.
go hello("Martin", c)
A hello
goroutine is created with go
. We pass the
channel as a parameter.
for msg := range c { fmt.Println(msg) }
With the range
keyword, we go through the messages and print them
to the console.
func hello(name string, c chan string) { for i := 0; i < 5; i++ { msg := fmt.Sprintf("Hello %s!", name) c <- msg time.Sleep(time.Millisecond * 500) } close(c) }
In the hello
function, we create five messages and send them via
the channel to the main
goroutine. When the goroutine is finished,
we close the channel with close
.
$ go run main.go Hello Martin! Hello Martin! Hello Martin! Hello Martin! Hello Martin!
Unidirectional channel example
In the following example, we use unidirectional channels.
package main import "fmt" func main() { c1 := make(chan int) c2 := make(chan int) go power(c2, c1) go power(c2, c1) go power(c2, c1) c2 <- 2 fmt.Println(<-c1) c2 <- 4 fmt.Println(<-c1) c2 <- 5 fmt.Println(<-c1) } func power(wc <-chan int, rc chan<- int) { num := <-wc res := num * num rc <- res }
In the program, we have a power
function which accepts a write-only
wc
channel and a read-only rc
channel.
$ go run main.go 4 16 25
Source
The Go Programming Language Specification
In this article we have worked with Go channels.
Author
List all Go tutorials.