← Back to Go Course | Chapter 11: Concurrency | Lesson 2 of 8

Channels

A channel is like a pipe between two goroutines -- one end drops messages in, the other end picks them up, in the order they were sent.

Creating and Using a Channel

make(chan Type) creates a channel that carries values of that type between goroutines. Values are sent with ch <- value and received with <-ch, and by default these operations block until the other side is ready.

Example: Creating and Using a Channel

markup
package main

import "fmt"

func main() {
	ch := make(chan string)
	go func() {
		ch <- "message from goroutine"
	}()
	msg := <-ch
	fmt.Println(msg)
}

Channels as Synchronization

Because a receive blocks until a value is sent, channels naturally synchronize goroutines -- the receiving side waits precisely until the sending goroutine has reached that point in its work.

Example: Channels as Synchronization

markup
package main

import "fmt"

func worker(done chan bool) {
	fmt.Println("working...")
	done <- true
}

func main() {
	done := make(chan bool)
	go worker(done)
	<-done
	fmt.Println("worker finished, main continues")
}

Closing a Channel

Closing a channel with close(ch) signals that no more values will be sent. Receivers can detect this with the comma-ok form, and range over a channel automatically stops when it's closed.

Note: Only the sender should close a channel -- closing a channel you're only reading from (or that's already closed) causes a panic.

Example: Closing a Channel

markup
package main

import "fmt"

func main() {
	ch := make(chan int)
	go func() {
		for i := 1; i <= 3; i++ {
			ch <- i
		}
		close(ch)
	}()
	for v := range ch {
		fmt.Println(v)
	}
}
Common Mistakes
  1. Sending on a channel that nobody is ever going to receive from, causing the sending goroutine to block forever (deadlock).
  2. Forgetting an unbuffered channel send blocks until a receiver is ready, and vice versa -- it's a rendezvous, not a mailbox.
  3. Reading from a closed channel expecting it to block or error, when it instead immediately returns the type's zero value.
Chapter Summary
  • A channel, created with make(chan Type), lets goroutines send and receive values safely.
  • Sending (ch <- v) and receiving (<-ch) on an unbuffered channel block until both sides are ready.
  • Channels are the idiomatic way to synchronize and communicate between goroutines, per Go's 'share memory by communicating' philosophy.
  • Reading from a closed channel returns the zero value immediately instead of blocking.
🔒

Chapter Quiz — Complete all 8 topics to unlock

0/8 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.