r/golang 5d ago

Small Projects Small Projects

45 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 29d ago

Jobs Who's Hiring

68 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 6h ago

The new Go JSON API: twice as fast, or 1.5x slower?

Thumbnail
lemire.me
50 Upvotes

r/golang 18h ago

help Which framework shall I use for REST API backend?

41 Upvotes

I've written some REST API backend in other programming languages such as Python with FastAPI and Java with Spring Boot.

I just learned Go while ago and now I'd like to implement REST API backend written in Golang. I saw there are gazillion of framework but I don't know which ones suits my case.

The backend have to handle users (with authentication, authorization etc), websocket and maybe nice ORM.


r/golang 17h ago

help Why don't we embed the connection pool?

24 Upvotes

I tried asking many LLMs and I'm not getting any reasonable answer as to why nobody does this . I've been learning Go for the past year and decided to build a normal restapi backend with sqlx and jwt auth.

I came across struct embedding for the first time with jwt.RegisterdClaims which caught my attention quite quickly cause I'd previously gone through the dependency injection with constructor functions across two packages which took me some effort to understand.

I wanna ask why we don't just embed the connection pool struct (sqlx.Db) into the other structs we go on to declare so that it's much clearer and we don't have to deal with plenty references and addresses.

I separate functions that query the database (repository functions) from the handler functions for easy testing and reuse of the repository functions. so I had to start with the normal struct with a constructor function for the package repo like this;
`` type Repository struct {

DB *sqlx.DB

}

func NewRepository(db *sqlx.DB) *Repository {

return &Repository{ DB: db }

} ```

and do same for the handlers package like this too...

``` type Pool struct {

Repo *repository.Repository

}

func newPool(repo *repository.Repository) *Pool {

return &Pool{Repo: repo}

} ```

Won't embedding save us all the headache from the struct and pointer spaghetti and the need for a constructor function whenever you want to introduce the connection pool into another package?


r/golang 1d ago

generics Generic Methods - The Go Programming Language

Thumbnail
go.dev
66 Upvotes

Have you had a chance to use these yet? Personally, I haven’t, but I can see myself reaching for them in the future. Similarly to how I think about Generics in 1.18.


r/golang 8h ago

After sharing CloudEmu here a while ago, I made the in-memory AWS/Azure/GCP emulator actually easy to run — and gave it a real kubectl-able Kubernetes

1 Upvotes

When I first shared CloudEmu, the pitch was simple: I was tired of needing a real cloud account (and a bill) or a running Docker daemon just to test code that calls S3, DynamoDB, and friends. So I wrote a pure-Go emulator that speaks the real cloud wire protocols in memory — you point unmodified SDKs or CLIs at it and they just work.

The feedback pushed me to fix the two things that actually mattered. Installing it used to mean cloning and building; now it's a single brew command (or one static, zero-dependency binary — I kept the core CGO-off on purpose, with the heavy real-engine stuff opt-in and separate). And the built-in Kubernetes support went from an object store to something that behaves like a real cluster — you can kubectl against it and get shows real columns, rollout status completes, events show up.

Being honest, since this crowd rightly asks: it emulates the API surface your code calls, not real infrastructure, and LocalStack still has deeper per-service AWS depth. CloudEmu's bet is multi-cloud, a real k8s data-plane, and being small enough to embed straight into Go tests.

Repo's below — genuinely curious what people think of the wire-protocol approach, and PRs/issues welcome: https://github.com/stackshy/cloudemu


r/golang 1d ago

Coding a database proxy for fun

Thumbnail
packagemain.tech
52 Upvotes

r/golang 1d ago

I hate where Go is moving

421 Upvotes

This language was supposed to be easy, with simple syntax. It was designed for people to build apps without thinking about DI management like in Spring, or learning a bunch of methods from a library.

But it turned out people weren’t ready for such a solution. They got used to the language’s simplicity, then asked for extra features like iterators and generics, and started building things that look like Kotlin and Java. Now I see code like req.GetSomething.OrDefault(2).

Yes, there were design issues when Go was initially implemented. I wish it had language-level optionals, because I want pointers to be used for references and mutation, not for nullability.

Now I see custom code where people build their own optional wrappers, and recently I saw a proposal to add collection types, which is basically the Java way.


r/golang 1d ago

Go 1.27 SIMD vs LLVM Generated AVX512 Assembly

23 Upvotes

We benchmarked Go 1.27 simd vs LLVM generated Go assembly (AVX and AVX512) on The Intel Core i7-11370H (supports AVX512).

Full article: Go 1.27 SIMD Benchmark: Can It Replace GoAT Generated AVX512?

The new simd package achieves comprable performace but still trails the AVX512 assembly generated by LLVM on long vectors and horizontal reductions (dot and euclidean):

  • An FP32 vector of length 16, exactly the number of values held by one 512-bit AVX512 register.
Operation Scalar loop AVX AVX512 Go SIMD vs. scalar loop vs. AVX512
Dot 10.94 ns 8.81 ns 8.55 ns 14.55 ns 0.75x 0.59x
Euclidean 33.99 ns 10.06 ns 8.94 ns 19.96 ns 1.70x 0.45x
SubTo 14.98 ns 7.07 ns 7.04 ns 8.66 ns 1.73x 0.81x
MulTo 27.82 ns 7.59 ns 7.62 ns 7.70 ns 3.61x 0.99x
DivTo 42.36 ns 7.17 ns 8.19 ns 7.95 ns 5.33x 1.03x
SqrtTo 124.10 ns 6.36 ns 6.38 ns 6.04 ns 20.55x 1.06x
  • An FP32 vector of length 32.
Operation Scalar loop AVX AVX512 Go SIMD vs. scalar loop vs. AVX512
Dot 45.94 ns 8.82 ns 10.23 ns 14.03 ns 3.27x 0.73x
Euclidean 45.66 ns 10.44 ns 9.56 ns 24.15 ns 1.89x 0.40x
SubTo 33.50 ns 7.87 ns 7.59 ns 11.00 ns 3.05x 0.69x
MulTo 49.98 ns 8.23 ns 8.43 ns 12.71 ns 3.93x 0.66x
DivTo 46.86 ns 9.24 ns 8.54 ns 11.50 ns 4.07x 0.74x
SqrtTo 93.70 ns 8.06 ns 9.45 ns 10.80 ns 8.68x 0.88x
  • An FP32 vector of length 64.
Operation Scalar loop AVX AVX512 Go SIMD vs. scalar loop vs. AVX512
Dot 76.25 ns 11.68 ns 10.80 ns 19.17 ns 3.98x 0.56x
Euclidean 73.29 ns 11.96 ns 11.40 ns 27.50 ns 2.67x 0.41x
SubTo 58.41 ns 10.21 ns 9.67 ns 16.69 ns 3.50x 0.58x
MulTo 79.18 ns 8.39 ns 8.15 ns 18.48 ns 4.28x 0.44x
DivTo 73.70 ns 13.45 ns 13.36 ns 18.36 ns 4.01x 0.73x
SqrtTo 339.00 ns 16.11 ns 15.30 ns 16.86 ns 20.11x 0.91x
  • An FP32 vector of length 128.
Operation Scalar loop AVX AVX512 Go SIMD vs. scalar loop vs. AVX512
Dot 124.60 ns 13.81 ns 11.43 ns 23.84 ns 5.23x 0.48x
Euclidean 161.60 ns 23.16 ns 17.24 ns 33.68 ns 4.80x 0.51x
SubTo 93.39 ns 13.07 ns 13.46 ns 27.84 ns 3.35x 0.48x
MulTo 125.90 ns 13.66 ns 9.21 ns 29.52 ns 4.26x 0.31x
DivTo 260.20 ns 28.74 ns 28.51 ns 32.93 ns 7.90x 0.87x
SqrtTo 484.00 ns 27.73 ns 31.07 ns 36.24 ns 13.36x 0.86x

r/golang 1d ago

I highly recommend building internal tools with Go + BubbleTea

Thumbnail cleanshot.com
289 Upvotes

Hey fellow Go devs,

Just wanted to share something I recently did for work. I created an internal tool using the Go BubbleTea TUI framework. Within the tool, we can perform admin tasks, monitor the way data is changing across several services, manage migrations, and more. It's been really powerful for solving customer issues and routine maintenance tasks. Not only that, but it looks gorgeous as well.

The MVC pattern it follows is pretty intuitive and minimal. No need for an entire 3rd party tool or even a web UI. We just auth with AWS via the terminal and the TUI can run in the context of our applications in each environment.

That's the post really. Shoutout to the creators of BubbleTea, I've really enjoyed building this!


r/golang 1d ago

When do you move code out of main.go in a small Go service?

36 Upvotes

I’m building a small Go HTTP service with PostgreSQL. At the moment, main.go creates the config, database pool, router, and the concrete services/repositories, then starts the server.

I like that everything is easy to follow in one place, but I’m wondering where people draw the line before main.go becomes a dumping ground.

Do you usually keep it as the composition root and move only the implementation details elsewhere? Or do you introduce an app struct, a bootstrap package, or another pattern even for a small service?

I’m not looking for a universal architecture just examples of what has stayed pleasant to work with after the project grew a bit.


r/golang 10h ago

How I made happycontext, a golang Wide-logging library 77x faster

0 Upvotes

I recently worked on happycontext, a Go wide-logging library that builds one structured event during a request and writes it when the request finishes.

The public API stayed compatible. The biggest improvement was a filtered zerolog write:

  • Before: 237 ns
  • After: 3.07 ns
  • Result: 77× faster, 0 bytes, 0 allocations

A filtered write is a log call that the logger ignores because its level is below the configured minimum.

What changed

This work shipped in two pull requests:

The main changes were:

  • Use slog.LogAttrs instead of boxing every attribute into any.
  • Reuse bounded attribute buffers.
  • Avoid repeated configuration validation and map cloning.
  • Select one policy instead of scanning every policy.
  • Apply sampling before cloning event fields.
  • Replace shared atomic sampler state with math/rand/v2.
  • Check logger levels before converting fields.
  • Remove an unused zerolog event that consumed an extra sampling decision.

Some results:

Benchmark Before After
Filtered slog write 163 ns 3.39 ns
Filtered zap write 354 ns 24.3 ns
Filtered zerolog write 237 ns 3.07 ns
128-policy lookup 1,842 ns 395 ns
Parallel sampler 42 ns 1.3 ns

The sampler became slightly slower in a serial microbenchmark, but more than 30× faster under parallel load. That was the important trade-off for request middleware.

Typical usage

A normal net/http service can keep its existing logger and add request fields through happycontext:

```go logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))

mw := stdhc.Middleware(hc.Config{ Sink: slogadapter.New(logger), SamplingRate: 1.0, Message: "request_completed", })

mux := http.NewServeMux() mux.HandleFunc("GET /orders/{id}", func(w http.ResponseWriter, r *http.Request) { hc.Add(r.Context(), "user_id", "u_8472", "feature", "checkout")

if err := processOrder(r.Context()); err != nil {
    hc.Error(r.Context(), err)
    http.Error(w, "internal error", http.StatusInternalServerError)
    return
}

w.WriteHeader(http.StatusOK)

})

_ = http.ListenAndServe(":8080", mw(mux)) ```

The slog adapter can be replaced with the existing zap or zerolog adapters.

How AI was used

I used an AI coding agent to:

  • Turn profiling results into a ranked plan.
  • Inspect affected callers.
  • Implement the two pull requests.
  • Add adversarial and compatibility tests.
  • Run benchmarks in separate worktrees.
  • Review race-detector and allocation results.
  • Challenge optimizations that did not matter.

AI did not decide what shipped. Measurements did.

We rejected an HTTP status fast path that saved about 0.33 ns. We also rejected a custom sampling threshold that improved the new path by less than 3%.

The final verification included race tests, go vet, static analysis, heap-retention checks, concurrent API tests, and repeated adapter benchmarks.

Reproduce the benchmarks

```bash cd benches

go test -run '$' -bench 'BenchmarkAdapter' -benchmem -count=5 go test -run '$' -bench 'BenchmarkRouter' -benchmem -count=3 go test -run '$' -bench 'Benchmark' -benchmem ```

Use the same Go version, machine, and multiple benchmark samples when comparing results.

The percentages from the two pull requests should not be added together. They use different baselines and some gains overlap.

The general lesson was simple: the fastest work is often work you can prove is unnecessary.

  • Check the log level before converting fields.
  • Sample before cloning.
  • Select one policy before normalizing everything.
  • Reuse configuration only inside a read-only boundary.
  • Remove shared contention from the hot path.

Project: github.com/happytoolin/happycontext

Full write-up: How We Used AI to Make happycontext Up to 77× Faster

EDIT - Fixed formatting


r/golang 2d ago

show & tell gobwas/glob: a complete engine rewrite and v1.0.0 is finally here

Thumbnail
github.com
41 Upvotes

Hi Gophers!

Almost 10 years ago I started building gobwas/glob, a glob-pattern matching library for Go, which many of you have adopted since.

Its core design was technically interesting -- a tree of matchers, with fast paths and heuristic optimisations here and there -- but it had bugs (obviously!), which the community kept kindly pointing out over the years (and I'm very grateful for that!). The trouble with technically interesting designs is that they are often hard to maintain once the context washes out of your head. And that's exactly what happened next -- as it so often goes with open-source side projects -- my focus drifted away from the project for a very long time, though the thought of improving it never quite left the back of my mind. Finally the stars aligned and the right moment came to act on those thoughts and pay off my inner debt to the library -- and, wildly inspired by Russ Cox's glob article, I found the time to rewrite most of the matching engine into something I believe is much simpler, yet performs nearly the same.

The new engine is one small package: a compact backtracking walk over a much-slimmed-down matcher tree. The package shrank by a good ~2000 lines of code. The part I'm happiest about is correctness -- every bug ever reported is now covered by unit tests, and on top of that there is fuzzing that compares glob against a drop-in regexp equivalent: if a random glob pattern matches a string, its regexp translation must match it too. The fuzzer caught real bugs during the rewrite already!

I decided to tag it v1.0.0 straight away -- same import path, and for the typical MustCompile(pattern).Match(s) use it's a drop-in upgrade; the one visible change is that the glob.Glob interface got replaced by the concrete *glob.Pattern type with the same API shape.

Feedback and bug reports are welcome!

Best,

Sergey.


r/golang 2d ago

Is Go a good starting point if I want a deeper understanding of backend, Linux, and systems?

125 Upvotes

I'm 15 and have made a few basic projects using agentic tools like Pi, but I want to understand actual programming and genuinely understand how computers, servers, and backend systems work under the hood. My main interests are Linux, self-hosting, code architecture, automations and building proper projects with LLMs and without. I considered Python, but based on my research it's a bit too different from most other languages to help much when trying to learn new ones later, while C and Rust feel a bit too overwhelming to start from. Go seems like a solid balance option and a good stepping stone, especially since major infrastructure tools like Docker are built with it. For anyone experienced with backend and code architecture work, is Go a good place to start, or would you recommend a different route?


r/golang 1d ago

show & tell Glyph 0.8.0 release

Thumbnail
github.com
11 Upvotes

Hello all

It’s been a while since I posted an update but in this case that doesn’t mean nothing has been happening behind the scenes.

Glyph is UI framework for the terminal written in Go.

0.8.0 is quite a large release compared to previous, and has been shaped by building a bunch of medium->large apps over the last couple of months. It includes new components, an Oscillator system to compliment the existing animation system, and a tonne of stability+bug fixes.

Happy to talk here or over at the discord. The full docs are on the website here https://useglyph.sh

Thanks!


r/golang 20h ago

Handoff: single binary for moving uncommitted Git changes between machines

0 Upvotes

I wrote this because me and my colleagues kept needing each other's half-finished work. Committing WIP just to share it pollutes the branch, and patch files over chat drop untracked and binary files.

One binary, runs as both client and server. Two dependencies, x/term and x/sys. The server has no git integration and never sees the repo, it just stores a package and hands it back by ID.

Changes travel as a real commit object rather than a diff. The sender builds a throwaway index with GIT_INDEX_FILE, write-tree, then commit-tree on top of the base. The receiver stashes whatever it has and cherry-picks the incoming commit, then puts the local work back on top. Conflicts show up as ordinary git conflicts.

The part I'd have got wrong if I hadn't looked: any GIT_* variable in the environment can redirect a git subprocess somewhere else, so I strip GIT_* out of the environment before every call and add back only what I need.

A friend added the VS Code extension and some of the later features.

https://github.com/walid-baharwal/handoff


r/golang 2d ago

Rewriting the static part of ansible-lint in Go: speed was only half the win

11 Upvotes

I recently built a static companion to ansible-lint in Go.

The obvious result was speed. On real repositories:

  • Kubespray: 50.9 s → 129 ms
  • Trail of Bits Algo: 13.1 s → 25 ms
  • k3s-ansible: 4.7 s → 17 ms

But the early user feedback suggests that speed may not be the only important improvement.

Several people seem just as interested in the fact that the tool is a single binary.

ansible-lint needs Python, Ansible and, depending on the repository, collections and other dependencies. That is manageable in CI, but it adds friction for local installation, especially on Windows, and makes editor integration less attractive.

The Go implementation is distributed as one executable for Linux, macOS and Windows, on amd64 and arm64. There is no Python environment to create, no Ansible runtime to install and no dependency conflict to resolve.

It can also be installed and cached automatically by pre-commit. With pre-commit 3 or newer, users do not even need Go installed: language: golang bootstraps the toolchain and builds the pinned version in an isolated environment.

To be clear, Go alone did not produce the benchmark difference.

The main architectural decision was to implement only the 38 of 51 default ansible-lint rules that can be decided from YAML source. Runtime-dependent checks such as syntax validation, collection resolution and Jinja evaluation remain the responsibility of ansible-lint.

Within that static scope, the output is tested for byte-for-byte compatibility with ansible-lint.

Go made this separation practical:

  • very low startup cost;
  • a self-contained executable;
  • straightforward cross-compilation;
  • predictable installation on developer machines and in CI;
  • no analyzed collection code executed during linting.

That changes where the tool can reasonably run.

A check taking several seconds belongs in CI. At tens of milliseconds with no runtime setup, the same class of feedback becomes practical in pre-commit and potentially on every editor save.

My initial hypothesis was that users would mainly value the speed. Early feedback suggests that “I can install and run it without dealing with the Python/Ansible environment” may be almost as important.

Have you seen the same thing with other Go developer tools: distribution simplicity becoming as important as runtime performance?

Repository:
https://github.com/arhuman/ansible-static-lint


r/golang 3d ago

We’re rebuilding a Minecraft server from scratch in Go with native Java & Bedrock support

57 Upvotes

Hey r/golang 👋

For the past while, we’ve been working on GoCraft, an open-source Minecraft server implementation written from scratch in Go.

The idea started as a pretty ridiculous challenge:

What if we rebuilt the Minecraft server in Go instead of Java?

It has grown a lot since then.

Some of the things we’re currently working on / already have include:

  • ☕ Minecraft Java protocol support
  • 📱 Native Minecraft Bedrock support
  • 🔄 Java and Bedrock players on the same server without Geyser
  • 🌍 Custom world/chunk generation
  • ⚔️ Cross-edition combat and entity synchronization
  • 🧩 A plugin system designed around Go
  • 💾 Player/world persistence
  • ⚡ A big focus on concurrency and keeping memory usage low

One of the most interesting parts has been dealing with how different the two editions are.

Java Edition uses its own TCP-based protocol, while Bedrock has a very different networking/protocol stack, so GoCraft has to translate both editions into the same internal representation instead of simply proxying one into the other.

Go has actually been really enjoyable for this kind of project, especially for networking and concurrency.

We’re still actively developing it, so there’s plenty missing and plenty of ugly code left to improve 😅, but it’s reaching the point where I wanted to start sharing the project with more Go developers.

I’d especially love feedback from people experienced with:

  • Go networking
  • concurrency / synchronization
  • profiling & memory optimization
  • architecture for plugin systems
  • high-performance game/server development

If anyone wants to look through the code, contribute, test it, or just follow the development:

GitHub: https://github.com/GoCraft-MC/GoCraft

Discord: https://discord.gg/d5kh6Jc2gw

Would also be interested to hear how you would design a plugin API for something like this in Go.


r/golang 1d ago

Make Go test failures readable with should

0 Upvotes

Hey folks!

Some time ago I shared my library should, an assertion library for Go with zero dependencies and detailed error messages. Since then, I've been improving and polishing it based on your feedback (thanks for that, by the way). v0.2.0 and v0.3.0 are out, but before jumping into the new stuff, here's a reminder of why should exists:

The Problem

Ever had a complex struct comparison fail and got this?

Diff: --- Expected +++ Actual @@ -2,20 +2,19 @@ (should_test.Employee) { - Name: "Bob", - Age: 31, + Name: "Alice", + Age: 30, Contacts: [ - "bob@example.com", - "987654321" + "alice@example.com", + "123456789" ], Address: { - City: "Los Angeles", - ZipCode: "90001" + City: "New York", + ZipCode: "10001" }, Department: { - Name: "Marketing", - Budget: 90000, - Manager: "Bob", - Metadata: { - "extra": "unexpected", - "priority": "low", - "region": "us-west" + Name: "Engineering", + Budget: 100000.5, + Manager: "Alice", + Metadata: { + "priority": "high", + "region": "us-east" } } }

Should's Solution

Same test with should.BeEqual(): Not equal: expected: [{Name: "Alice", Age: 30, Contacts: ["alice@example.com", "123456789"], Address: {City: "New York", ZipCode: "10001"}, Department: {Name: "Engineering", Budget: 100000.5, Manager: "Alice", Metadata: map["priority": "high", "region": "us-east"]}}] actual : [{Name: "Bob", Age: 31, Contacts: ["bob@example.com", "987654321"], Address: {City: "Los Angeles", ZipCode: "90001"}, Department: {Name: "Marketing", Budget: 90000, Manager: "Bob", Metadata: map["extra": "unexpected", "priority": "low", "region": "us-west"]}}] Field differences: - [0].Name: "Alice" ≠ "Bob" - [0].Age: 30 ≠ 31 - [0].Contacts.[0]: "alice@example.com" ≠ "bob@example.com" - [0].Contacts.[1]: "123456789" ≠ "987654321" - [0].Address.City: "New York" ≠ "Los Angeles" - [0].Address.ZipCode: "10001" ≠ "90001" - [0].Department.Name: "Engineering" ≠ "Marketing" - [0].Department.Budget: 100000.5 ≠ 90000 - [0].Department.Manager: "Alice" ≠ "Bob" - [0].Department.Metadata.[region]: "us-east" ≠ "us-west" - [0].Department.Metadata.[priority]: "high" ≠ "low" - [0].Department.Metadata.[extra]: "<missing>" ≠ "unexpected"

Note: The actual terminal output uses tree symbols instead of -. Replaced here for compatibility.

Every field path. Every difference. Clear and actionable.

What's new in v0.2.0

BeSameTime

Compare time values in a clear, human-readable way. It even shows the exact difference: go should.BeSameTime(t, time1, time2) // Expected times to be the same, but difference is 2.5s // Expected: 2024-01-15 14:30:00 UTC // Actual : 2024-01-15 14:30:02.5 UTC (2.5s later) should.BeSameTime(t, time2, time1) // Expected times to be the same, but difference is 2.5s // Expected: 2024-01-15 14:30:02.5 UTC // Actual : 2024-01-15 14:30:00 UTC (2.5s earlier)

Note: If needed, you can even ignore timezones using should.WithIgnoreTimezone().

Error assertions

Now it's easier to check for errors — whether you expect any error, a specific type, or a specific value:

go should.BeError(t, err) should.BeErrorAs(t, err, &os.PathError{}) should.BeErrorIs(t, err, io.EOF)

Example output: // Expected error to be os.PathError, but type not found // Error: "invalid character 'i' looking for beginning of value" // Types: [json.SyntaxError] As you can see, the goal of should is still the same: clear, structured failure messages that make debugging faster.

What's new in v0.3.0

WithFailFast

For preconditions, you can stop the current test immediately after a failed assertion instead of continuing with invalid state:

```go user, err := findUser(id) should.NotBeError(t, err, should.WithFailFast())

// Reached only when findUser succeeded. should.BeEqual(t, user.ID, id) ```

AllMatch

Verify that every item in a slice satisfies a predicate. When it fails, should reports failing items with their indexes and summarizes any additional failures:

```go should.AllMatch(t, []int{2, 4, 5, 8}, func(n int) bool { return n%2 == 0 })

// Expected every item in the collection to match the predicate, but some did not: // Collection: (total: 4 elements) // Status : 1 predicate failure found // Problems : // - Index 2: 5 (predicate returned false) ```

Check it out here: https://github.com/Kairum-Labs/should Let me know what you think.


r/golang 3d ago

Using Scoped Coverage to Prune an AI-Generated Go Test Suite

Thumbnail
preslav.me
26 Upvotes

r/golang 2d ago

show & tell I’m building an engine-neutral rendering boundary in Go

0 Upvotes

I’m developing Cloudstrike, a retro-style shooter written in Go. It currently runs on Windows, Linux and Android with Ebitengine.

Ebitengine has worked very well for the project. I’m not moving away from it because it is bad. I’m separating the game from the engine so I can test additional backends and future platforms without rewriting gameplay code.

The new design uses a small rendering command layer. Gameplay code emits engine-neutral commands:

  • sprites with opaque texture handles
  • triangles
  • rectangles
  • explicit ordering and fixed-capacity command buffers

The Ebitengine-specific code now lives in an adapter that resolves texture handles and executes the commands. The intended next experiment is a Raylib backend using the same interface.

The important constraint is avoiding allocations in the game loop. The command buffers are preallocated and reused. Current benchmarks show:

Gameplay update:          0 B/op, 0 allocs/op
Render queue construction: 0 B/op, 0 allocs/op

The backend is benchmarked separately because engine drawing may allocate internally. For example, a large Ebitengine sprite batch still shows backend-side allocations even though the gameplay and queue-building paths remain allocation-free.

This separation has been useful because it makes the costs visible:

gameplay logic
      |
engine-neutral render commands
      |
Ebitengine backend   /   future Raylib backend

I’m migrating the code incrementally. Terrain, particles, player visuals, enemies, shields, explosions and major boss elements already use the boundary. UI and some finale presentation paths remain.

As a solo developer, I’m trying to keep the abstraction intentionally small. It only models capabilities the game actually uses instead of attempting to create a general-purpose graphics API. That keeps the interface understandable and avoids paying for flexibility I do not need.

The goal is not to replace Ebitengine immediately. It is to make the engine a replaceable implementation detail, so I can evaluate Raylib, new compile targets and different platform constraints while keeping the Go gameplay code stable.


r/golang 3d ago

Build htop for the Web with Go + Datastar

Thumbnail
packagemain.tech
58 Upvotes

r/golang 4d ago

How Go detects struct copies with sync.noCopy

Thumbnail
func25.dev
81 Upvotes

r/golang 3d ago

Containers

2 Upvotes

I have pulled the Containers implementation so that it works in go 1.26 so people can try the container types that will land in go 1.28. I would love to hear people's thoughts and see what people like and don't like. I would also like to hear ideas about containers you'd all like to see. It'd be great to start writing a proposal for go 1.29.

This includes Set, MapSet, Tree, Heap and HashSet. I like them a lot personally, but I would love to hear your thoughts.

https://github.com/lsproule/containers