Golang chan keyword
last modified May 7, 2025
This tutorial explains how to use the chan keyword in Go. We'll
cover channel basics with practical examples of concurrent programming.
The chan keyword declares a channel type for communication between goroutines. Channels are typed conduits that let you send and receive values.
In Go, chan is fundamental for safe concurrent programming. Channels
synchronize goroutines and prevent race conditions by design.
Basic channel creation
The simplest use of chan creates an unbuffered channel. This example
demonstrates basic channel declaration and usage.
package main
import "fmt"
func main() {
// Create an unbuffered channel of integers
ch := make(chan int)
go func() {
// Send value through channel
ch <- 42
}()
// Receive value from channel
val := <-ch
fmt.Println("Received:", val)
}
The channel ch transmits an integer between goroutines. The main
goroutine blocks until the value is received.
Buffered channels
Buffered channels allow sending multiple values without blocking. This example shows how to create and use them.
package main
import "fmt"
func main() {
// Create a buffered channel with capacity 3
ch := make(chan string, 3)
// Send values without blocking
ch <- "first"
ch <- "second"
ch <- "third"
// Receive values
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
}
The channel holds three strings before blocking. Values are received in FIFO order. Buffered channels decouple senders and receivers.
Channel directions
Channel parameters can be restricted to send-only or receive-only. This example demonstrates directional channels.
package main
import "fmt"
// sendOnly can only send to channel
func sendOnly(ch chan<- int, val int) {
ch <- val
}
// receiveOnly can only receive from channel
func receiveOnly(ch <-chan int) int {
return <-ch
}
func main() {
ch := make(chan int)
go sendOnly(ch, 99)
val := receiveOnly(ch)
fmt.Println("Received:", val)
}
Directional channels make function contracts clearer. chan<- is
send-only, while <-chan is receive-only.
Channel synchronization
Channels can synchronize goroutines. This example shows a common worker pattern.
package main
import (
"fmt"
"time"
)
func worker(done chan bool) {
fmt.Print("Working...")
time.Sleep(time.Second)
fmt.Println("done")
done <- true
}
func main() {
done := make(chan bool)
go worker(done)
// Block until worker finishes
<-done
fmt.Println("Worker completed")
}
The main goroutine waits for the worker to signal completion. Channels provide simple synchronization without locks.
Select statement with channels
The select statement handles multiple channel operations. This
example demonstrates non-blocking channel operations.
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
ch1 <- "one"
}()
go func() {
time.Sleep(2 * time.Second)
ch2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println("Received", msg1)
case msg2 := <-ch2:
fmt.Println("Received", msg2)
}
}
}
select waits on multiple channel operations. It executes the first
ready case. This is useful for timeouts and multiplexing.
Channel timeouts
Channels can implement timeouts using select. This example shows
how to prevent indefinite blocking.
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan string)
go func() {
time.Sleep(3 * time.Second)
ch <- "result"
}()
select {
case res := <-ch:
fmt.Println(res)
case <-time.After(2 * time.Second):
fmt.Println("timeout")
}
}
time.After creates a channel that sends after the duration. The
select chooses between the result and timeout.
Closing channels
Closing channels signals no more values will be sent. This example demonstrates proper channel closing.
package main
import "fmt"
func producer(ch chan int) {
for i := 0; i < 5; i++ {
ch <- i
}
close(ch)
}
func main() {
ch := make(chan int)
go producer(ch)
for {
val, ok := <-ch
if !ok {
fmt.Println("Channel closed")
break
}
fmt.Println("Received:", val)
}
}
The producer closes the channel after sending all values. Receivers can detect closure using the second return value.
Source
This tutorial covered the chan keyword in Go with practical
examples of channel usage in concurrent programming.
Author
List all Golang tutorials.