A JSON REST API built with Fiber and Gloat, demonstrating Go/Clojure interoperability for web applications.
make serveThis installs all dependencies (Go, Gloat, Glojure) locally via Makes, compiles the Clojure handlers to Go, builds the binary, and starts the server on port 3000.
# Health check
curl localhost:3000/health
# Add items
curl -X POST -d '{"name":"milk"}' localhost:3000/api/items
curl -X POST -d '{"name":"eggs"}' localhost:3000/api/items
# List all items
curl localhost:3000/api/items
# Get one item
curl localhost:3000/api/items/1
# Toggle done status
curl -X PUT localhost:3000/api/items/1/toggle
# Delete an item
curl -X DELETE localhost:3000/api/items/1Fiber is a Go web framework inspired
by Express.
It requires Go handler functions with the signature
func(*fiber.Ctx) error.
Glojure (the Clojure-to-Go compiler underlying Gloat) does not support
deftype or reify, so there is no way to implement a Go interface or
pass a Clojure function directly as a Go callback.
The solution splits responsibilities across two files:
handlers.clj -- Pure functional Clojure containing all request
logic:
- Each handler receives a request map (
:method,:path,:body,:id, etc.) and returns a response map (:status,:body) - JSON encoding/decoding happens inside Clojure via
ys.json - State is managed with Clojure atoms (in-memory, no persistence)
shim.go -- A Go shim that:
- Creates a Fiber app and registers routes
- For each route, wraps a Clojure handler function: builds a request
map from
fiber.Ctx, invokes the handler, and extracts:status(int64) and:body(string) from the response map - Go never inspects the JSON payloads -- they stay as strings
serialized by
ys.json/dumpinside Clojure
The key design choice is where JSON serialization happens.
By doing it inside Clojure (using ys.json/dump and ys.json/load),
the Go shim only needs to extract two simple values from the Clojure
response map: an integer status code and a string body.
Go never walks Clojure persistent data structures.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check |
GET |
/api/items |
List all items |
GET |
/api/items/:id |
Get item by ID |
POST |
/api/items |
Add item |
PUT |
/api/items/:id/toggle |
Toggle done status |
DELETE |
/api/items/:id |
Delete item |
gloat --module=... handlers.clj -o build/compiles the Clojure handlers to a Go module directory with a generatedmain.go- The generated
main.gois replaced withshim.go(with the module path substituted in) - Fiber is added to
go.mod, thengo mod tidy && go buildproduces the binary