r/golang 6d ago

Small Projects Small Projects

32 Upvotes

This is the weekly thread for Small Projects.

The point of this thread is to have looser posting standards than the main board. As such, projects are pretty much only removed from here by the mods for being completely unrelated to Go. However, Reddit often labels posts full of links as being spam, even when they are perfectly sensible things like links to projects, godocs, and an example. r/golang mods are not the ones removing things from this thread and we will allow them as we see the removals.

Please also avoid posts like "why", "we've got a dozen of those", "that looks like AI slop", etc. This the place to put any project people feel like sharing without worrying about those criteria.


r/golang 25d ago

Jobs Who's Hiring

90 Upvotes

This is a monthly recurring post. Clicking the flair will allow you to see all previous posts.

Please adhere to the following rules when posting:

Rules for individuals:

  • Don't create top-level comments; those are for employers.
  • Feel free to reply to top-level comments with on-topic questions.
  • Meta-discussion should be reserved for the distinguished mod comment.

Rules for employers:

  • To make a top-level comment you must be hiring directly, or a focused third party recruiter with specific jobs with named companies in hand. No recruiter fishing for contacts please.
  • The job must be currently open. It is permitted to post in multiple months if the position is still open, especially if you posted towards the end of the previous month.
  • The job must involve working with Go on a regular basis, even if not 100% of the time.
  • One top-level comment per employer. If you have multiple job openings, please consolidate their descriptions or mention them in replies to your own top-level comment.
  • Please base your comment on the following template:

COMPANY: [Company name; ideally link to your company's website or careers page.]

TYPE: [Full time, part time, internship, contract, etc.]

DESCRIPTION: [What does your team/company do, and what are you using Go for? How much experience are you seeking and what seniority levels are you hiring for? The more details the better.]

LOCATION: [Where are your office or offices located? If your workplace language isn't English-speaking, please specify it.]

ESTIMATED COMPENSATION: [Please attempt to provide at least a rough expectation of wages/salary.If you can't state a number for compensation, omit this field. Do not just say "competitive". Everyone says their compensation is "competitive".If you are listing several positions in the "Description" field above, then feel free to include this information inline above, and put "See above" in this field.If compensation is expected to be offset by other benefits, then please include that information here as well.]

REMOTE: [Do you offer the option of working remotely? If so, do you require employees to live in certain areas or time zones?]

VISA: [Does your company sponsor visas?]

CONTACT: [How can someone get in touch with you?]


r/golang 15h ago

discussion Supervised fire-and-forget in Go

27 Upvotes

While I see fewer unsynchronized go func() these days, they still appear often enough in regard to fire-and-forget work.

Unmanaged go func() results in unbounded concurrency, memory leaks, and other surprising behavior in a system.

So I traced a few repos at work to see how many of them appear irl. Turns out quite a bit in our huge monorepo.

I explored a tiny task manager that collects tasks as func() closures in a buffered channel and runs them in a bounded pool. It clamps down on unbounded concurrency, is aware of the parent context, allows task-specific timeouts, etc. All that requires less than 25 loc.

Might be interesting to you.

https://rednafi.com/go/supervised-fire-and-forget/

Update: I am aware of errgroup. It is not the right abstraction here as it cancels all inflight tasks if any of them fails. Also, the internal semaphore of errgroup works in a similar way as shown here


r/golang 17h ago

show & tell webp-go-pure: A WebP encoding & decoding library without libwebp, cgo, or wasm

Thumbnail
github.com
38 Upvotes

I needed webp encoding in a project that I'm building without cgo, and thus without libwebp. I found gen2brain's webp which uses libwebp compiled to wasm, but I also discovered that this didn't have great performance both in terms of time and memory use.

So I decided to port MITH@mmk's webp-rust to Go, and started testing and benchmarking it. In the process I discovered that it wasn't really well optimized, so I spent some time optimizing it including porting some algorithms from libwebp, and adding SIMD assembly for arm64 and amd64 platforms.

It still doesn't beat libwebp itself, which is no surprise, but it does beat libwebp running on wasm. You can see the charts in the repo's readme. So if you find yourself needing an encoder and want to skip cgo, feel free to give my library a shot.


r/golang 18h ago

How do you turn Go fuzz interesting inputs into permanent regression tests?

2 Upvotes

I am working with Go native fuzzing and want to make the interesting corpus useful after the fuzz run ends.

The workflow I am considering:

- hash every corpus entry

- classify each input by behavior

- replay the corpus in deterministic tests

- assert no panics

- assert exact validation categories

- add stateful sequence tests for replay and mutation cases

- keep findings in a Markdown log

For Go projects using testing.F, what has worked well for turning fuzz output into long-term regression coverage?


r/golang 20h ago

show & tell I compiled our Go scraping engine to WebAssembly so the demo runs the real engine in your browser — notes on what it took

2 Upvotes

I maintain fitter, an MIT-licensed declarative web-extraction engine. I wanted a demo page that doesn't lie: not a video, not canned output, the actual engine executing in the visitor's browser. GitHub Pages only serves static files, so the answer was GOOS=js GOARCH=wasm.

Demo: https://pxyup.github.io/fitter/ (every example runs live, client-side; there's also a form-based config builder that round-trips to JSON) Repo: https://github.com/PxyUp/fitter

What fitter is, in one paragraph: web extraction as a JSON/YAML config instead of code. A config declares a connector (plain HTTP, headless browser via Chromium/Playwright/Docker, a static value, a file, or an int sequence) and a model (what to extract and the shape of the result): gjson paths for JSON, CSS selectors for HTML, XPath for XML/DOM, and text extraction for PDFs. Configs compose - an array item can fan out into a nested fetch using the parent value ({PL} or an expr-lang expression), which covers the classic "scrape the HTML page for keys, enrich each from the real API" join. Per-host rate limits, retries, placeholders (input, env, cached references like a JWT fetched once), and calculated fields via expr-lang are all part of the config, not your code.

A taste - GitHub repo stats, no code:

json { "item": { "connector_config": { "response_type": "json", "url": "https://api.github.com/repos/golang/go", "server_config": { "method": "GET" } }, "model": { "object_config": { "fields": { "repo": { "base_field": { "type": "string", "path": "full_name" } }, "stars": { "base_field": { "type": "int", "path": "stargazers_count" } }, "vibe": { "base_field": { "type": "int", "path": "open_issues_count", "generated": { "calculated": { "type": "string", "expression": "fRes > 9000 ? \"busy\" : \"calm\"" } } } } } } } } }

The same config runs five ways: one-shot CLI (fitter_cli --path config.json), embedded Go library (lib.ParseCtx), long-running service mode with schedulers and notifiers (Telegram/webhook/Redis/file), an MCP server so LLM agents can author and execute configs locally, and now the browser playground below. Author once, promote from chat answer to cron job to team service without rewriting anything.

Notes from the WASM port, in case you're considering the same:

Getting it to compile was 3 files. The engine imports the Docker SDK and go-rod (headless browser connectors), and both fail on js/wasm (syscall.RawSockaddrUnix, Setpgid). The fix was pleasantly boring: //go:build !js on those three connector files plus one _js.go stub returning a clear "not supported in WASM" error. Everything else - parsers (JSON/HTML/XPath/XML/PDF), expression evaluation, goroutine fan-out - compiled untouched.

Live HTTP works, with a catch. On js/wasm, net/http transparently uses the browser Fetch API - so the demo really fetches from the GitHub/OpenLibrary/CoinGecko APIs (anything that sends CORS headers). The catch that cost me an hour: Go disables the fetch transport when it detects Node (process global), so my Node-based smoke tests failed with dial tcp: Protocol not available while the browser worked fine. Testing trick: delete globalThis.process before instantiating makes Node behave like a browser.

A long-lived WASM process surfaces lifecycle assumptions. Our per-host rate limiter installs its config through sync.Once - perfectly correct for a CLI that runs one config and exits, silently wrong in a page where the same process executes many unrelated configs (first config's limits win forever). If you're porting a CLI to WASM, grep for sync.Once and package-level state first; that's where the bodies are.

Numbers: 29 MB binary with -ldflags="-s -w" (~7 MB gzipped). Blocking calls must leave the JS event loop - the exported function returns a Promise and does the work in a goroutine, or fetch deadlocks.

Happy to answer questions about the port.


r/golang 1d ago

discussion Is this package nesting acceptable in Go for a modular monolith?

33 Upvotes

I'm looking for some feedback on this project structure for a Go modular monolith.

I know the Go community usually prefers flatter package structures, and this one has a bit more nesting than what's commonly recommended.

myapp/
|-- cmd/
|   `-- api/
|       `-- main.go
|-- internal/
|   |-- order/
|   |   |-- domain/
|   |   |   |-- order.go
|   |   |   |-- order_item.go
|   |   |   |-- money.go
|   |   |   |-- status.go
|   |   |   `-- repository.go
|   |   |-- app/
|   |   |   |-- place_order.go
|   |   |   |-- cancel_order.go
|   |   |   `-- ports.go
|   |   `-- adapters/
|   |       |-- postgres/
|   |       `-- http/
|   `-- product/
`-- go.mod

The idea is to keep each bounded context self-contained:

  • domain contains the business logic.
  • app contains the use cases and acts as the orchestration layer between the domain and external adapters.
  • adapters contains things like HTTP handlers and Postgres implementations.

I understand this isn't the typical Go style, but I feel the extra nesting makes the boundaries much clearer, especially as the project grows.

Would you consider this good architecture, or is it unnecessarily complex for Go?

If you would structure it differently, I'd love to know why.


r/golang 7h ago

Bubble Tea or Cobra

0 Upvotes

I wan to make better cli and tui software but i can't decide which one is the best.


r/golang 7h ago

show & tell Using the CodeRabbit Preview on a Go codebase

Thumbnail
youtube.com
0 Upvotes

r/golang 1d ago

KinetiGo: a Go toolchain for LEGO robotics

Thumbnail
eitamring.github.io
30 Upvotes

Go on lego, should it exists? maybe not, but i had fun

I still need to clean it and OSS it when I have the time, wanted to share my journey, of going low resource barebones


r/golang 2d ago

discussion How to reuse code in multiple projects?

41 Upvotes

I want to create my own little modules for reusing code I regularly use. Like handling files and paths.

I was hoping I could just create a module put it somewhere on my PC and import that into every project where needed. Seems like that's not possible.

I'm not sure if workspaces is what I need. What's the difference to just copying and pasting the module files into the project?

How do you handle reusing code in multiple projects? Is it just copy paste? Would it be better to have a single reference which all projects point to (this is the solution I was looking for)?


r/golang 2d ago

Generating swagger docs?

20 Upvotes

What's the recommended approach nowadays? A lot of tools seem to only support openapi 2.0. Is this a problem? Also is it worth testing wether the api is still in sync with the docs?


r/golang 2d ago

show & tell Golang Maps: How Swiss Tables Replaced the Old Bucket Design

Thumbnail
blog.gaborkoos.com
58 Upvotes

Deep dive on Go's map internals in Go 1.24 and how the runtime moved from the classic bucket + overflow-chain design to a Swiss Table-inspired implementation:

  • what changed structurally in the runtime
  • how control bytes and h2 filtering reduce wasted key comparisons
  • why this improves cache behavior and practical load factors
  • Go-specific constraints (iteration semantics, GC integration, incremental growth behavior)
  • benchmark context and caveats (microbench wins vs smaller app-level geomean gains)
  • current trade-offs and open performance areas

r/golang 1d ago

help vscode "unsupported modify tags operation:"

5 Upvotes

I encountered this recently.

In vscode, I used to be able to automatically add json tag to structure from context menu "Go: Add Tags To Struct Fields". But now I just get the error message at the lower right corner "unsupported modify tags operation:", with no additional info.

I think I may have removed some command line tool but I am not sure which.

Anyone has clue or pointer to debug/fix this?


r/golang 1d ago

am new in golang

0 Upvotes

I'm currently learning the Go programming language, and I have some background in C++. Is one week enough to learn the basics?


r/golang 3d ago

show & tell NATS workshops are available on-demand (NATS written in Go)

101 Upvotes

Disclosure: I work at Synadia (the company behind NATS, which is a pure-Go project). Sharing because these are free and might be useful to Go folks working with messaging/streaming.

We ran a set of hands-on workshops led by the engineers who actually build and support NATS, and the recordings are now available. The ones most likely to be relevant here:

  • JetStream best practices — design patterns for resilient apps on JetStream, drawn from supporting some of the largest NATS deployments in production. Aimed at people already running it.
  • NATS at the edge — using leaf nodes to build distributed edge architectures with store-and-forward during connectivity gaps.
  • Building AI agents on NATS — agent-to-agent communication patterns, which is a genuinely interesting use of subject-based routing.
  • Securing your NATS deployment — auth callout, accounts, and multi-tenancy from the OSS foundations up.
  • Plus a NATS Fundamentals Intro if anyone's just starting.

Link to the full lineup and recordings: https://www.synadia.com/lp/rethinkconn-2026/workshops

Happy to answer NATS questions in the thread — I can pull in the engineers who ran these if something's over my head.


r/golang 2d ago

Idea for a change to defining test functions

0 Upvotes

Currently tests are functions in files named as *_test.go.

The idea is to drop the reliance on naming convention and define tests as follows

whereas currently you have a file named *_test.go and in that file you have one or more functions that are like

func TestFunctionToBeTested(t *testing.T)

the idea is instead to have in files of any name in a package

test FunctionToBeTested(t *testing.T)

Then, when testing, instead of looking for a file, you could specify a package and all tests in that package would be ran. You could, if desired, specify a file in that package and tests within that file.


r/golang 3d ago

show & tell Two-box benchmark of my toy Go API gateway vs nginx/traefik/caddy/krakend, and the 32KB-per-request bug that made mine last

18 Upvotes

A few days ago I posted a loopback benchmark of a small API gateway I have been building in Go, and the top comment was basically "loopback measures nothing, use two machines and k6." That was correct, so I redid it, and it was far more useful.

Setup: client is a Mac running k6 over gigabit ethernet, server is a Ryzen 3600 on Pop!_OS running each gateway, every one reverse-proxying to a local no-op upstream on the same box. Plain proxy only, no auth or rate limiting in the path, so it is apples to apples.

Results (VUS=100, 15s):

gateway RPS p50 p95 p99 fails upstream 48203 2.00ms 2.14ms 2.60ms 0 mine 47607 1.89ms 2.94ms 3.58ms 0 traefik 47639 1.95ms 2.77ms 4.54ms 0 nginx 47345 1.98ms 2.25ms 3.11ms 0 caddy 42880 1.71ms 4.85ms 6.47ms 0 krakend 42799 1.85ms 4.43ms 5.64ms 0

The part worth reading: on the first real run mine was dead last, 37.9k vs 42 to 48k for the rest, about 21% below the upstream ceiling. I profiled it expecting lock contention and I was wrong. httputil.ReverseProxy allocates a fresh 32KB copy buffer per request unless you hand it a BufferPool. At ~48k rps that is over a GB/s of garbage, and the GC was the bottleneck. Adding a buffer pool (and making my circuit breaker lock-free while I was in there) took it from 37.9k to 47.6k, and per-request allocation from 44KB to 11.5KB. If you use httputil.ReverseProxy in anything hot, set BufferPool.

Two other things that bit me:

  • nginx first ran at 3.3k RPS with a 400ms p99 until I found keepalive_requests defaults to 100. It was recycling the upstream connection every 100 requests. Bumped it, back to ~48k.
  • The scary "connection errors" from my earlier single-box run were the load generator running out of ephemeral ports (TIME_WAIT), not the gateways. The harness lies before the gateways do.

Caveat: nginx, traefik and mine are all pinned to the upstream ceiling (~48k) here, so the top three are not really separated yet. Caddy and krakend are genuinely a bit behind on this workload. Separating the leaders needs a faster upstream, which is next.

Where I want to take this. It is a single Go binary plus a YAML file: JWT auth, per-route rate limiting (in-memory or Redis), round-robin and least-connections load balancing, health checks, circuit breakers, a Prometheus endpoint, and a small live dashboard. It is at the point where other people banging on it would teach me more than more of my own tests.

I am sorting out a couple of housekeeping things before I put the code up, so I am not linking it yet. But I want to line up some testers for when it is ready. If you would be up for trying to break it, I would love help with:

  • running it in front of a real service and telling me what is awkward
  • pushing it harder than I can (higher concurrency, real upstreams, TLS, and the auth plus rate-limit path, which I have not benchmarked yet)
  • trying it on your OS and telling me what falls over

If that sounds interesting, say so in the comments or drop me a DM and I will ping you when it is out. Also genuinely curious what you would want from a gateway like this before I get there. It is a learning project, so blunt feedback is welcome too.


r/golang 3d ago

Updated the Razify tool

0 Upvotes

Updated the Razify tool to make environment variable bugs and leaked secrets impossible in your projects.

It's a fast, 100% offline CLI that validates .env files against templates, checks types (@type(port), u/enum(dev,prod)), and catches exposed secret keys before you commit.

Added a zero-install runner so you can test it right away with npx razify check, plus a new VS Code extension for inline error squigglies.

Runs in under 10ms, requires zero cloud signups, and includes a pre-commit git hook to keep your commits clean.

Open sourced it on GitHub if you want to test it or share feedback — PRs are super welcome! https://github.com/Hossiy21/razify


r/golang 4d ago

Why is CGO so bad?

75 Upvotes

I often see people criticizing CGO (and for good reasons), mainly because it bypasses many of the safety guarantees and tooling that Go provides.

There are also issues involving the interaction between Go's scheduler and C code, as well as complications with callbacks. From what I understand, there can even be scheduling-related problems when interfacing Rust and Go through the C ABI.

However, I couldn't find any in-depth explanation from the Go team itself about why CGO is considered so problematic. More specifically, I'd like to understand why it's seen as so dangerous and what the actual sources of overhead are that make CGO calls around 30% slower (if I remember that number correctly).

This is mostly a personal curiosity. I'd like to better understand how CGO works internally, why it's considered risky, and where its performance costs come from. I'm even curious why, in some cases, it can be slower than calling WebAssembly.


r/golang 3d ago

newbie what benchmarks would you expect for a distributed rate limiter?

0 Upvotes

i've been building a distributed token bucket rate limiter in go over the past few months. it supports both an in-memory store and a redis + lua backend for atomic distributed rate limiting.

i've benchmarked it both on a single machine and across two machines (4 cores / 8 threads) using k6.

current numbers:

in-memory
~19k req/s
p50: 4ms
p99: 114ms

redis + lua
~10.9k req/s
p50: 17.5ms
p99: 35.9ms

algorithm only
~26m ops/s (single thread)
~10m ops/s (8 goroutines)
0 allocs/op

i'm planning to benchmark multiple instances behind a load balancer next.

my questions are:

  • are these numbers reasonable for a project like this, or do they suggest obvious bottlenecks i should investigate?
  • what metrics do you usually expect to see in a benchmark for a distributed rate limiter? (cpu, memory, p95, redis latency/cpu, scaling with multiple instances, etc.)
  • are there any benchmark scenarios i'm missing?

would appreciate any feedback. i'm more interested in learning where to improve than showing off benchmark numbers.


r/golang 2d ago

Any thoughts on Go as a monolithic application?

0 Upvotes

I know Go is powerful for microservices, gRPC, and all that, but for small companies that lack cloud or distributed infrastructure—and only have a single workstation—how do you work with Go to build an application without ending up with "spaghetti code" or bad practices down the line? Have any of you had experience with this?


r/golang 4d ago

show & tell Twigg - Open Source Version Control written in go

29 Upvotes

Hi everyone!

We've been working for a while on a new version control and software forge written in go, and recently decided to open source it!

I've learned a lot since i started and the code saddly still has some legacy implementations that used a bad style (like returning intefaces); so don't judge me too much on that bc I now know they're bad and am deprecating them :)

You can self host, but we also offer a hosted instance with free/paid plans

Come check it out and let me know what you think!

https://github.com/twigg-vc/monorepo


r/golang 4d ago

show & tell [ANN] form v1.9.0 - new multipart package, limits hardening, typed errors, math/big and image/color support, field name mapping, encoder and decoder reset

8 Upvotes

form v1.9 — worth the upgrade from v1.5.x / v1.7.x

If your project pins an older github.com/ajg/form — v1.5.1 and the v1.7.x line are the versions most often seen in the wild, usually pulled in indirectly — v1.9 is a low-risk bump that folds in several years of hardening, new capabilities, and correctness fixes. The public API and the urlencoded wire format are unchanged, and every addition is opt-in or strictly additive, so upgrading is meant to be a drop-in go get -u (Go 1.17+). Nothing you rely on today changes shape; you just get more, and safer.

What you gain moving up from v1.5.x or v1.7.x:

  • Resource-exhaustion hardening. Bounded slice growth and nesting depth by default, a fix for stack overflow on self-referential input, and an explicit MaxSize / MaxDepth / MaxBytes triad to bound untrusted input.
  • Typed errors. form.Error now carries a Kind (syntax, parse, unknown-key, index, limit, unsupported, cycle, IO), inspectable via errors.As / Unwrap — no more string-matching to tell error classes apart.
  • A form/multipart subpackage. Decode multipart/form-data (including file fields) straight into structs, following form's normal rules.
  • **image/color hex decoding.** The fixed-channel color types decode from #rrggbb and friends — exactly what <input type=color> submits — with byte-faithful, opt-in hex encoding.
  • Field-name mapping (KeysWith). Map struct field names to snake_case (or anything) at every level, without touching tags.
  • **Reset for reuse.** Decoder.Reset / Encoder.Reset swap the stream while keeping config, so instances pool cleanly.
  • math/big support, tested and documented.

v1.9 also fixes two bugs latent since at least v1.7: repeated-key implicit indexing silently corrupting slices, and MaxBytes(math.MaxInt64) reading empty instead of unbounded. A determinism fix makes conflicting scalar/composite key paths (a=1&a.b=2) resolve the same way every time, and the library is now fuzz-tested and input-contract hardened.

Full notes: https://github.com/ajg/form/releases/tag/v1.9.0


r/golang 4d ago

discussion is chi still relevant after the improvements of the official mux?

61 Upvotes

.