{"id":51061371,"url":"https://github.com/tomi77/zmq4","last_synced_at":"2026-06-23T02:30:31.939Z","repository":{"id":355289525,"uuid":"1227500459","full_name":"tomi77/zmq4","owner":"tomi77","description":"Pure-Go implementation of ZeroMQ speaking ZMTP 3.1","archived":false,"fork":false,"pushed_at":"2026-05-12T17:59:31.000Z","size":1272,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-12T19:30:19.463Z","etag":null,"topics":["zmq","zmq-library"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tomi77.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-02T19:14:48.000Z","updated_at":"2026-05-12T17:59:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tomi77/zmq4","commit_stats":null,"previous_names":["tomi77/zmq4"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/tomi77/zmq4","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomi77%2Fzmq4","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomi77%2Fzmq4/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomi77%2Fzmq4/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomi77%2Fzmq4/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomi77","download_url":"https://codeload.github.com/tomi77/zmq4/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomi77%2Fzmq4/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34673437,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["zmq","zmq-library"],"created_at":"2026-06-23T02:30:30.856Z","updated_at":"2026-06-23T02:30:31.928Z","avatar_url":"https://github.com/tomi77.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zmq4\n\n[![CI](https://github.com/tomi77/zmq4/actions/workflows/ci.yml/badge.svg)](https://github.com/tomi77/zmq4/actions/workflows/ci.yml)\n\nPure-Go [ZeroMQ](https://zeromq.org/) speaking [ZMTP 3.1](https://rfc.zeromq.org/spec/23/). No `cgo`. No `libzmq`.\n\n## Installation\n\n```sh\ngo get github.com/tomi77/zmq4@latest\n```\n\n## Quick start\n\n```go\nctx := context.Background()\n\nrep := zmq4.NewREP(zmq4.WithNULL())\n_ = rep.Bind(ctx, \"tcp://127.0.0.1:5555\")\ndefer rep.Close()\n\nreq := zmq4.NewREQ(zmq4.WithNULL())\n_ = req.Connect(ctx, \"tcp://127.0.0.1:5555\")\ndefer req.Close()\n\n_ = req.Send(ctx, zmq4.NewStringMsg(\"Hello\"))\nmsg, _ := rep.Recv(ctx)   // msg.String() == \"Hello\"\n_ = rep.Send(ctx, zmq4.NewStringMsg(\"World\"))\nreply, _ := req.Recv(ctx) // reply.String() == \"World\"\n```\n\n## Socket patterns\n\n### Request-Reply ([RFC 28](https://rfc.zeromq.org/spec/28/))\n\n`REQ` → `REP`: strict alternating send/receive.\n`DEALER` → `ROUTER`: async, no alternation constraint.\n\n```go\nrep := zmq4.NewREP()\nreq := zmq4.NewREQ()\n```\n\nSee [`examples/hello-world/`](./examples/hello-world/) and [`examples/router-dealer/`](./examples/router-dealer/).\n\n### Publish-Subscribe ([RFC 29](https://rfc.zeromq.org/spec/29/))\n\n```go\npub := zmq4.NewPUB()\nsub := zmq4.NewSUB()\n_ = sub.Subscribe(\"prices\") // subscribe to topic prefix\n```\n\n`XPUB`/`XSUB` extend the pattern: `XPUB` can inspect subscription frames; `XSUB` can send them manually — enabling forwarding proxies.\n\nSee [`examples/pubsub/`](./examples/pubsub/) and [`examples/xpubxsub-proxy/`](./examples/xpubxsub-proxy/).\n\n### Pipeline ([RFC 30](https://rfc.zeromq.org/spec/30/))\n\n```go\npush := zmq4.NewPUSH()\npull := zmq4.NewPULL()\n```\n\n`PUSH` distributes tasks round-robin across all connected `PULL` workers.\n\nSee [`examples/pipeline/`](./examples/pipeline/).\n\n### Exclusive Pair ([RFC 31](https://rfc.zeromq.org/spec/31/))\n\n```go\na := zmq4.NewPAIR()\nb := zmq4.NewPAIR()\n```\n\nExactly one peer; bidirectional.\n\nSee [`examples/pair/`](./examples/pair/).\n\n## Security\n\nSelect a mechanism via constructor options:\n\n```go\n// No authentication (default).\nzmq4.NewREP(zmq4.WithNULL())\n\n// PLAIN — username/password (RFC 24).\nzmq4.NewREQ(zmq4.WithPLAIN(\"alice\", \"s3cr3t\"))          // client\nzmq4.NewREP(zmq4.WithPLAINServer(myAuthenticator))       // server\n\n// CURVE — public-key encryption (RFC 25/26).\nzmq4.NewREQ(zmq4.WithCURVE(clientOptions))               // client\nzmq4.NewREP(zmq4.WithCURVEServer(serverOptions))         // server\n```\n\nSee [`examples/curve-security/`](./examples/curve-security/) for a self-contained CURVE example.\n\n## Benchmarks\n\nMeasured on Apple M1 (darwin/arm64), Go 1.24.\nCompared against [go-zeromq/zmq4](https://github.com/go-zeromq/zmq4) v0.17.0 and [pebbe/zmq4](https://github.com/pebbe/zmq4) v1.4.0 (cgo wrapper over libzmq 4.3.5).\n`go-zeromq` and `pebbe` support TCP only (inproc skipped).\n\nEach benchmark pattern runs in its own process (`-benchtime=3s -count=5`) so accumulated\nGC pressure from earlier runs cannot skew later results. Numbers are medians across the 5\nruns. Use `benchmarks/scripts/bench.sh` to reproduce.\n\n```\ncd benchmarks \u0026\u0026 ./scripts/bench.sh           # tomi77 + go-zeromq\ncd benchmarks \u0026\u0026 ./scripts/bench.sh -tags libzmq  # include pebbe (requires libzmq)\n```\n\n### PAIR · one-way throughput (MB/s)\n\n| Message size | tomi77 inproc | tomi77 tcp | go-zeromq tcp | pebbe tcp |\n|---|--:|--:|--:|--:|\n| 64 B   |         197 |    26.5 |     8.8 |   174   |\n| 1 KiB  |       3 119 |   406   |   134   | 1 434   |\n| 64 KiB |     203 000 | 5 540   | 3 923   | 3 445   |\n| 1 MiB  | 3 252 000 † | 8 009   | 5 888   | 4 844   |\n\n### PUSH/PULL · one-way throughput (MB/s)\n\n| Message size | tomi77 inproc | tomi77 tcp | go-zeromq tcp | pebbe tcp |\n|---|--:|--:|--:|--:|\n| 64 B   |         189 |    23.7 |     8.9 |   175   |\n| 1 KiB  |       3 087 |   372   |   134   | 1 367   |\n| 64 KiB |     194 000 | 5 182   | 3 442   | 3 326   |\n| 1 MiB  | 3 089 000 † | 6 528   | 7 022   | 4 849   |\n\n### PUB/SUB · send-side throughput (MB/s) ‡\n\n| Message size | tomi77 inproc | tomi77 tcp | go-zeromq tcp | pebbe tcp |\n|---|--:|--:|--:|--:|\n| 64 B   |   598   |   340   |    95   |   402   |\n| 1 KiB  | 2 618   | 1 133   |   980   | 3 496   |\n| 64 KiB | 7 308   | 5 570   | 1 934   | 5 204   |\n| 1 MiB  | 6 293   | 9 600   | 1 916   | 4 593   |\n\n† Inproc messages are delivered as Go channel values without copying bytes through\nthe wire — the reported MB/s reflects message-rate × size and is not bounded by memory\nbandwidth.  \n‡ PUB drops messages when the outbound queue is full; numbers reflect send-side rate and\nhave high run-to-run variance (±2×) due to the interaction between drop policy and\ngoroutine scheduling.\n\n### REQ/REP · round-trip latency (µs/op)\n\n| Message size | tomi77 inproc | tomi77 tcp | go-zeromq tcp | pebbe tcp |\n|---|--:|--:|--:|--:|\n| 64 B   |  1.37 |  27.5 |  36.7 |   84.8 |\n| 1 KiB  |  1.35 |  28.1 |  40.2 |   88.7 |\n| 64 KiB |  1.33 |  53.4 |  66.4 |  132.4 |\n| 1 MiB  |  1.33 | 293   | 276   |  510   |\n\n### Heap allocations per operation (tcp)\n\n| Pattern   | tomi77 | go-zeromq | pebbe |\n|---|--:|--:|--:|\n| PAIR      |  3 | 26 | 1 |\n| PUSH/PULL |  3 | 26 | 1 |\n| PUB/SUB   | 4–5 | 10–17 | 2–3 |\n| REQ/REP   |  8 | 32 | 4 |\n\n## Non-goals (for now)\n\n- Backwards compatibility with ZMTP 3.0 / 2.0 / 1.0.\n- Draft socket types (`CLIENT`/`SERVER`, `RADIO`/`DISH`, `SCATTER`/`GATHER`, `STREAM`).\n- Higher-level patterns (Majordomo, Clone, Freelance, Zyre) — those may live in separate modules later.\n\n## Documentation\n\nFull API reference: [pkg.go.dev/github.com/tomi77/zmq4](https://pkg.go.dev/github.com/tomi77/zmq4)\n\nDesign documents: [`docs/specs/`](./docs/specs/)\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomi77%2Fzmq4","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomi77%2Fzmq4","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomi77%2Fzmq4/lists"}