liveBook · Manning

Close function

As explained in Learn Go with Pocket-Sized Projects

The close function is a Go built-in that marks a channel as closed so that no more values can be sent on it and receivers can detect completion.

When a goroutine has finished sending on a channel, call Go’s built-in `close(c)` to mark that channel closed for writing. Receivers can still read values already sent. Once those are exhausted, a receive returns the channel’s element type’s zero value; a send is no longer possible, and closure cannot be undone. section 7.2.3 section 9.5.2

Signal that a task is done

A worker can notify its caller with `c := make(chan struct{}, 1)`. In a deferred function, it sends `struct{}{}` and then calls `close(c)`; the caller waits with `_ = <-c`. An empty structure carries no task data—the receive is the notification. Placing the notification in a defer keeps it tied to the worker’s return. section 7.2.3

Closure is especially useful when several goroutines need the same quit signal. Sending one value would wake one receiver; sending enough values would require knowing how many workers remain. Instead, close the quit channel when the solution is found. Each worker can then receive from that closed channel and stop. section 9.5.2

Listing 9.26 explore.go: Stop listening to new messages
func (s *Solver) listenToBranches() {
    wg := sync.WaitGroup{}
    defer wg.Wait()

    for {
        select {
        case <-s.quit: #1
            log.Println("the treasure has been found, stopping worker")
            return
        case p := <-s.pathsToExplore: #2
            wg.Add(1)
            go func(p *path) {
                defer wg.Done()

                s.explore(p)
            }(p)
        }
    }
}

The branch listener includes `<-s.quit` in a `select` and returns when the quit channel becomes readable. It also waits for the exploration goroutines it started. section 9.5.2

Keep the receiving code aligned with what closure means:

  • Use `value, ok := <-c` when the value matters: `ok` distinguishes a sent value from the zero value returned after closure. A quit-only channel needs no such check if nothing is sent on it. section 9.5.2
  • A `range` over a channel waits for messages while the channel remains open. Closing the channel lets that listening pattern finish, but it does not by itself track whether goroutines started from those messages have finished. section 9.3.4
  • When a worker may either publish another job or quit, put the receive and send in the same `select`. A separate nonblocking quit check followed by a send leaves a gap in which the quit channel can close. section 9.5.2
select {
case <-s.quit:
    log.Printf("I'm an unlucky branch, someone else found the treasure, I 
give up at position %v.", pos)
    return
case s.pathsToExplore <- branch:
    //continue execution after the select block

}

This `select` places the quit receive beside the branch send, avoiding the separate-check-then-send pattern. section 9.5.2

Do not confuse built-in `close(c)` with a file’s `f.Close()` method. The former ends channel sends and provides a completion signal; the latter releases file resources and is commonly deferred immediately after a successful `os.Open`. section 7.2.3 section 3.1.2

How Learn Go with Pocket-Sized Projects covers it

How deep it goes
Explains reads after closure, zero values, two-value receives, and shutdown patterns; does not examine runtime internals.
Examples
Shows a buffered completion channel and a concurrent maze solver whose workers stop through a quit channel.
What it assumes
Assumes familiarity with Go functions and goroutines while introducing channel creation, sends, receives, and directional channel parameters.
What you can do after
Practice/perform channel closure to notify waiting goroutines and distinguish completion from a sent zero value.
How it connects
Connects close to goroutines, channels, select, channel range, and two-value receives.

Also explained in

Compare how 3 books explain close function →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Go with Pocket-Sized Projects. The section links point to the parts of the book it draws on.