Made a small progress bar for the first release of Solod (a subset of Go that translates to C).
Not quite there yet, but a lot of work is already done!
Posts by Anton Zhiyanov
But sometimes, maps are really useful for small, local tasks like routing or counting.
So, I eventually made a stack-allocated version of the map[K]V built-in. It's lightweight and super fast — sometimes even faster than Go's map (which is already state-of-the-art).
When I designed Solod (a subset of Go that translates to C), I set a strict rule: no heap allocations in the language or built-ins (only in the standard library).
That meant no built-in maps.
Maps are essential in application development. But Go's stdlib uses maps very cautiously.
I've ported a dozen core Go packages to C so far and have encountered a map only a couple of times.
The fewer maps, the better!
Can a C port of the Go stdlib be faster than the original?
I was able to get a 2-4x speed boost with strings.Builder, but couldn't beat Go's substring search.
On porting, benchmarks, and optimization: antonz.org/porting-go-s...
Details: github.com/solod-dev/so...
Solod (a subset of Go that translates to C) shines when it comes to C interop. But it's also quite fast on regular Go code.
In this strings.Builder benchmark — a common, optimized case in Go — Solod performs 2-4 times faster.
And the binary is only 53K (vs. 1.6M with Go).
While porting Go's standard library to C, I try to avoid heap allocations as much as possible.
Of course, sometimes there's no way around them, like in os.ReadFile.
But often I can use local stack allocations or a buffer provided by the caller instead.
It's working pretty well.
If you stare into Go's stdlib long enough, you start seeing things.
Dark things. Things you weren't meant to see.
Like this function that uses variables named φ and β.
In today's crazy world, writing C is the only sane thing to do.
P.S. You don't need AI; you have AI in netdb.h.
Solod playground
Solod (a subset of Go that translates to C) now has an online playground!
I guess that means it's a real language now 😁
codapi.org/so
The "io" package is a core part of Go's standard library. Porting it to C was an interesting challenge.
I had to figure out how to handle slices, multiple return values, errors, and interfaces in C. But in the end, it worked out pretty well!
antonz.org/porting-go-io
Could Go be a better C? I think so!
Meet Solod — a strict subset of Go that translates to C, without hidden memory allocations and with source-level interop.
antonz.org/solod
Such a terrible development 😐
Honestly, even with just the syntax, writing C has become more pleasant for me personally.
The end goal is also to port Go's stdlib.
So, it's not just about the syntax! :)
But it supports custom allocators, so a tracking allocator (once I write one) should help with temporal safety.
As for safety — not much too. Out-of-bounds — yes, use-after-free and dangling pointers — no. Using GCC/Clang sanitizer flags helps up to a point.
Not much so far. I started small, so right now it's just bytes, io, unicode, and a few others. I'd say it's more about adapting than reimplementing — most of the code works fine. But yeah, it's not exactly a walk in the park :)
The basic approach is this:
// panics on failure
func Alloc[T any](a Allocator) *T
// returns an error
func TryAlloc[T any](a Allocator) (*T, error)
Unfortunately, it's not as easy with stdlib, where a lot of functions allocate, and having Try-versions doubles the API surface. We'll see.
That's the whole point :) Why would I want a garbage collector when Go already has one?
The big idea is to bring the power of Go's standard library to C, so everyone can use it without any extra overhead.
Working on something crazy these days — using Go to write regular C code. Wish me luck :)
Thank you for sharing, Laurent!
How to implement "defer" keyword in C (allows to free memory and other resources correctly): implementations with C23/GCC, C11/GCC, GCC/Clang... - Blog Post by Anton Zhiyanov @antonz.org #Programming antonz.org/defer-in-c/
What makes modern systems languages stand out? Many things — but allocators are a big one.
Let's explore how Rust, Zig, Odin, C3, and Hare design their allocators, and then build one in C!
antonz.org/allocators
Go 1.26 is out, and the announcement says:
"Over the next few weeks, follow-up blog posts will cover some of the topics in more detail. Check back later."
So you can wait a few weeks OR you can read my interactive Go 1.26 tour right away:
antonz.org/go-1-26
SwissTable, a high-performance open-addressing hash map originally developed by Google, is becoming more popular in the industry.
First, Rust adopted it for its HashMap type. Then Go started using SwissTable for its map type.
And now — Valkey. Pretty cool!
valkey.io/blog/new-has...
Fancy an allocator in C? It's not Zig, but it's honest work.
We don't need to wait for "defer" to be added to the C standard. We already have defer at home!
antonz.org/defer-in-c
The only two features I really miss in C at this point are namespaces and defer.
With Go 1.26, you can easily log to multiple targets (like stdout, a file, or a remote server) using just the standard library.
All thanks to slog.MultiHandler, which sends log records to any number of handlers you configure.