← 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.
Syntax
go
ch := make(chan type)
ch <- value   // send
value := <-ch // receive
close(ch)

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
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// main is where the program starts running
func main() {
	// Short declaration: create ch and infer the type
	ch := make(chan string)
	// Start this call in a new goroutine (runs concurrently)
	go func() {
		ch <- "message from goroutine"
	}()
	// Short declaration: create msg and infer the type
	msg := <-ch
	// Print the values followed by a newline
	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
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// Define the function worker
func worker(done chan bool) {
	// Print the values followed by a newline
	fmt.Println("working...")
	done <- true
}

// main is where the program starts running
func main() {
	// Short declaration: create done and infer the type
	done := make(chan bool)
	// Start this call in a new goroutine (runs concurrently)
	go worker(done)
	<-done
	// Print the values followed by a newline
	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
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// main is where the program starts running
func main() {
	// Short declaration: create ch and infer the type
	ch := make(chan int)
	// Start this call in a new goroutine (runs concurrently)
	go func() {
		// Loop: repeat while the condition holds
		for i := 1; i <= 3; i++ {
			ch <- i
		}
		close(ch)
	}()
	for v := range ch {
		// Print the values followed by a newline
		fmt.Println(v)
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
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.