channel
A channel is a mechanism for safely passing data between goroutines. Because send and receive operations are synchronized, goroutines can communicate without using mutexes.
Syntax
// Creates a channel (unbuffered).
ch := make(chan type)
// Creates a buffered channel.
ch := make(chan type, bufferSize)
// Sends a value to the channel (blocks until received).
ch <- value
// Receives a value from the channel (blocks until sent).
v := <-ch
// Closes the channel (the sender closes it).
close(ch)
// Receives while checking whether the channel is closed.
v, ok := <-ch // If ok is false, all values have been received (the channel is closed).
// Receives all values from the channel using range (loops until closed).
for v := range ch { ... }
Channel Types
| Type | Description |
|---|---|
| Unbuffered (make(chan T)) | Blocks unless a send and receive happen at the same time. Used to synchronize goroutines. |
| Buffered (make(chan T, n)) | Sends do not block until the buffer is full. Receives block when the buffer is empty. |
| Send-only (chan<- T) | A channel type that only allows sending. Used in function parameters to restrict a channel to the sender side. |
| Receive-only (<-chan T) | A channel type that only allows receiving. Used in function parameters to restrict a channel to the receiver side. |
Sample Code
package main
import "fmt"
// A function that takes a send-only channel as an argument.
func produce(ch chan<- int, count int) {
for i := 0; i < count; i++ {
ch <- i // Sends a value to the channel.
}
close(ch) // Closes the channel to signal that sending is done.
}
// A function that takes a receive-only channel as an argument.
func consume(ch <-chan int, done chan<- bool) {
for v := range ch { // Keeps receiving until the channel is closed.
fmt.Printf("Received: %d\n", v)
}
done <- true // Signals that processing is complete.
}
func main() {
// Example of an unbuffered channel (synchronization between goroutines).
ch := make(chan int)
done := make(chan bool)
go produce(ch, 5)
go consume(ch, done)
<-done // Waits for consume to finish.
fmt.Println("---")
// Example of a buffered channel.
buffered := make(chan string, 3)
buffered <- "first" // Does not block because the buffer has space.
buffered <- "second"
buffered <- "third"
// buffered <- "fourth" // Would cause a deadlock because the buffer is full.
fmt.Println(<-buffered) // Prints "first".
fmt.Println(<-buffered) // Prints "second".
fmt.Println(<-buffered) // Prints "third".
// Using a channel to signal goroutine completion.
quit := make(chan struct{}) // Using struct{} is idiomatic when the value is not needed.
go func() {
fmt.Println("goroutine running")
close(quit) // Closes the channel to signal completion.
}()
<-quit // Blocks until the channel is closed.
fmt.Println("goroutine done")
}
Overview
Go follows the design philosophy of "do not communicate by sharing memory; instead, share memory by communicating." Channels are the mechanism that makes this possible, enabling safe data transfer and synchronization between goroutines.
Sending to a closed channel causes a panic. Always close a channel on the sender side — never on the receiver side.
To wait on multiple channels at once, use select. For launching and managing goroutines, see goroutine.
If you find any errors or copyright issues, please contact us.