Back to Blog

Clojure for Beginners: Clojure core.async — Channels and Go Blocks (CSP Concurrency)

Celest KimCelest Kim

Video: Clojure core.async — Channels and Go Blocks (CSP Concurrency) | Episode 29 by CelesteAI

Watch full page →

Clojure core.async — Channels and Go Blocks (CSP Concurrency)

Clojure has one more concurrency story, and it's the one that scales furthest: **CSP-style** — Communicating Sequential Processes. Instead of shared state with locks (atoms, refs, agents), you build producers and consumers as independent lightweight processes (`go` blocks) that pass messages through channels.

Code

(ns app.core
  (:require [clojure.core.async :as a
             :refer [chan >! <! <!! go go-loop close! timeout]]))

(defn -main
  "Run with: clj -M:run"
  [& _]
  (let [ch (chan 3)]
    (println "── producer / consumer over a channel ──")

    ;; Producer go block: 5 messages, 100ms apart, then close
    (go
      (dotimes [i 5]
        (>! ch {:n i :msg (str "payload-" i)})
        (<! (timeout 100)))
      (close! ch))

    ;; Consumer go-loop: read until the channel closes (nil)
    (<!!
      (go-loop []
        (when-let [v (<! ch)]
          (println "consumer got:" v)
          (recur))))

    (println "channel closed, consumer done"))

  (shutdown-agents))

Key Points

Watch the video above for a full walkthrough — every keystroke is shown so you can code along.

Student code: GitHub