Communicating sequential processes (CSP) models a concurrent program as independent processes that pass messages rather than coordinate through shared memory. This addresses a practical problem on multicore machines: manual synchronization can tangle concurrency with application logic and introduce intermittent races or deadlocks. section 1.4
Go applies this approach through goroutines and channels. A channel is a typed conduit: goroutines send and receive values with the <- operator. That gives pipeline stages a way to exchange work and coordinate without explicit locking. Channels support patterns such as fan-in, fan-out, and worker pools. section 9.4
Fetching and storing articles
A feed-fetching goroutine sends parsed articles over a channel while a storage goroutine receives them and adds them to an article store. The fetcher can use a send-only channel reference, and the storage function can accept a receive-only channel. An HTTP handler then exposes recently stored articles as JSON. section 9.4
Listing 9.18 main.go: Adding functions to fetch and save articles
func (a *App) fetchFeed(ctx context.Context, url string) {
...
fmt.Println("fetched: ", url)
var writeChan chan<- *gofeed.Article #1
out := make(chan *gofeed.Article)
writeChan = out #2
go a.saveFeed(out)
defer close(out)
for _, article := range feed.Article{
fmt.Println("ingesting article: ", article.Link)
writeChan <- article
}
fmt.Println("processed: ", url)
}
func (a *App) saveFeed(articles
<-chan *gofeed.Article) { #3
fmt.Println("adding articles...")
for article := range articles {
fmt.Println("adding article: ", article.Link)
a.store.AddArticle(article)
fmt.Println("article added: ", article.Link)
}
fmt.Println("all articles added")
}
The feed-fetching and storage functions show how directional channel types make each goroutine’s communication role explicit. section 9.4

