Field manual & progression chart — Go 1.26

Gopher
Grid

Twenty-two learning points, three tiers, and a MIDI/OSC router for your own rig at the end. Nodes unlock when their prerequisites clear, and a node only clears on evidence — a command that runs, a test that passes, a race the detector cannot find.

Toolchain go1.26.6 darwin/arm64
Dependencies zero until node 18, then one
Assessed level JS/TS senior · Go day zero

The 2–3 day project · nodes 16–22

conduit

A MIDI/OSC router you can put in a live set. It replaces pendulum/sender/midi-to-osc.mjs and then goes past it: every controller at once, several destinations at once, a musical clock, a routing table you can rewrite from your phone mid-set, and a panic button that actually stops the sound. You already know this signal flow, so all the difficulty lands on Go rather than on the problem.

What it must do

  • Read every connected MIDI controller at once
  • Listen for OSC on UDP 9000 — pendulum's bridge port
  • Fan out to Max, TouchDesigner and the bridge together
  • Play MIDI into Ableton over IAC Driver Bus 1
  • Run a clock the other sources can lock to
  • Remap a route over HTTP without restarting
  • Ctrl-C sends all-notes-off before it exits

What it exercises

  • Goroutine per source — every controller, socket and the clock
  • One channel as the event bus, select to merge them
  • RWMutex on the routing table — audio path reads, HTTP writes
  • Non-blocking send — a wedged destination drops, never stalls
  • Context cancellation — one Ctrl-C, everything unwinds
  • cgo, and exactly where the single-binary story stops

Rough shape

// router.go
type Event struct {
	Addr string      // "/midi/cc/74"
	Args []float32
	From string      // "nord", "osc:9000", "clock"
}

type Router struct {
	mu     sync.RWMutex
	routes []Route
	dests  map[string]chan Event
}

func (r *Router) Route(e Event)
Illustrative — you write the bodies
Where the single binary stops The OSC half is stdlib and pure Go: GOOS=linux GOARCH=amd64 go build produces a static Linux ELF from your Mac, verified. The MIDI half is not — gomidi's rtmidi driver is a C++ library through cgo, and that same command fails with build constraints exclude all Go files. It compiles and runs natively here in a few seconds against Xcode's clang, and IAC Driver Bus 1 is already enabled, so Ableton needs no setup at all. If you ever want a headless OSC-only node on the performance network, put the MIDI driver behind a build tag. That split is the honest shape of the tradeoff, not a workaround.