liveBook · Manning

Channel

As explained in Go in Practice, Second Edition

A Go channel is a typed communication mechanism that transfers values between goroutines and synchronizes their execution.

A Go channel is a typed path for sending values between goroutines. Create one with `make(chan int)`, send with `c <- value`, and receive with `value := <-c`. An unbuffered send waits for a receiver, so the handoff also synchronizes the goroutines. Channels can carry structured data without marshaling it into bytes. section 1.2.3 section 5.3 section 5.3.3

Send values and finish cleanly

For a finite stream, let the sender close the channel after its last send. The receiver checks whether each receive succeeded: package main import "fmt" func main() { messages := make(chan string) go func() { messages <- "ready" messages <- "done" close(messages) }() for { message, ok := <-messages if !ok { return } fmt.Println(message) } } Do not close a channel while another goroutine may still send to it: sending on a closed channel panics. In a long-running sender, a separate `done` channel can communicate that it is time to stop and close the message channel. section 1.2.3 section 5.3.2

Use a buffer when a send must proceed before a receiver is ready: `make(chan bool, 1)` has room for one value. That capacity also makes a simple lock possible. Send to acquire it; receive to release it. Another goroutine trying to send while the buffer is full waits. An unbuffered channel cannot serve this pattern because its first send would wait for a receive. section 5.3.3

Listing 5.11 Simple locking with channels
package main

import (
    "log"
    "time"
)

func main() {
    lock := make(chan bool, 1) //      #1
    for i := 1; i < 7; i++ { //         #2
        go worker(i, lock) //           #2
    }
    time.Sleep(10 * time.Second)
}

func worker(id int, lock chan bool) {
    log.Printf("%d wants the lock\n", id)
    lock <- true //                             #3
    log.Printf("%d has the lock\n", id) //             #4
    <-lock //                                      #5
    log.Printf("%d is releasing the lock\n", id)
}

The complete worker example shares a one-slot channel among goroutines and shows each worker acquiring and releasing the lock. section 5.3.3

Channels also carry control signals, not just application data. A signal channel can receive an operating-system interrupt while a server runs concurrently; after receiving the signal, the program can request a graceful shutdown. If other goroutines must finish too, coordinate them separately. section 2.3.2

How Go in Practice, Second Edition covers it

How deep it goes
Works through send/receive syntax, blocking, safe closure, and buffered locking; defers channel-system theory and underpinnings.
Examples
Uses integer handoffs, a sender-closure example, a one-slot worker lock, and an OS-signal-driven server shutdown.
What it assumes
Introduces goroutines and the `go` keyword before channels, while using basic Go functions and loops.
What you can do after
Build it from scratch to exchange typed values between goroutines and coordinate a sender-owned channel shutdown.
How it connects
Connects goroutines and channels to buffering, mutexes, OS signals, and graceful shutdown.

Also explained in

Compare how 10 books explain channel →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go in Practice, Second Edition. The section links point to the parts of the book it draws on.