Build1 publisher3 min readPublished Updated
Goish ports Go 1.25's runtime into no_std Rust to test what the concurrency model is worth alone
A one-person project translates Go's scheduler, channels, net/http and crypto/tls into Rust with no GC, no glibc and no Tokio, and stamps every function with its Go source line.
The Engineer · Build desk
Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction
What happened
- Goish is a project published at goish.cogentica.ai, covered in an August 2026 dev.to post.
- Goish is the work of Chanwit Kaewkasi (@chanwit), a Thai engineer from Korat, under the company Cogentica AI.
- Goish is described as a port of Go 1.25's standard library and runtime into no_std Rust, depending on neither glibc, Rust's std, Tokio, nor a garbage collector.
- Goish ships its own components from _start onward: page allocator, size-class heap, M:N scheduler, channels, select!, sync primitives, net/http and crypto/tls.
- The result is a single static binary like Go's, and running ldd on it reports "not a dynamic executable".
Compiled by The EngineerSomething wrong?How this is made
Why it matters
Chanwit Kaewkasi, a Thai engineer from Korat working under Cogentica AI, has released Goish, described on its own site as a port of Go 1.25's standard library and runtime into no_std Rust [1][2][3]. The interesting part is not that it compiles; it is that it forces a question Go users usually leave vague, which is how much of Go's value is the concurrency model and how much is the runtime underneath it.
According to the project, Goish depends on neither glibc, Rust's std, Tokio, nor a garbage collector, and ships everything itself from `_start` upward: page allocator, size-class heap, M:N scheduler, channels, `select!`, sync primitives, `net/http` and `crypto/tls` [3][4]. The output is a single static binary, and the post reports `ldd` answering "not a dynamic executable" [5]. The tagline is "A Rust runtime for Go people" [6].
The scheduler is not a lookalike. The post says `runtime/proc.go` from Go 1.25 was translated line by line, including per-P lock-free SPMC run queues of 256 entries with global overflow, coprime-permuted work stealing via `runqgrab`, `runqsteal` and `stealOrder`, async preemption through SIGURG, a `sysmon` handling the timer heap and forced preemption, and a per-P epoll netpoller that parks the goroutine rather than blocking the thread [12][13][14][15][16][17]. The allocator keeps Go's mheap to mcentral to per-P mcache shape and its 67 size classes, but deletes the collector and leaves reclamation to Rust ownership [18][19].
That deletion is the load-bearing bet, and stacks are where it shows. Each goroutine gets a 1 MiB virtual reservation with lazy commit, so a shallow goroutine costs roughly one 4 KiB page of real memory, and `go!(stack(2*KB), ...)` requests a 2 KiB stack from a pool for density work [20][21]. The demo table shows RSS of 44,800 KB at baseline and 2,406,528 KB with one million parked goroutines, with thread count unchanged at 13 and no drift by 30 seconds [22][23]. That works out to about 2.36 KiB of RSS per goroutine and roughly 77,000 goroutines per OS thread [24][25].
The stated motivation is not ergonomics but provenance. The argument in the post is that SLSA attestations and SBOMs describe how a binary was built, not whether translated code was translated faithfully, and that an SBOM entry reading "goish 0.1.0" cannot distinguish reviewed crypto from an approximation [7][8]. So each port carries a comment naming its origin, in the form `// go: sdk 1.25.5 crypto/internal/fips140/aes/gcm/gcm.go:31-46 newGCM`, and CI opens the Go tree on every commit to verify the cited line ranges still point where they claim [9][10]. The post frames this as a response to approaching legal deadlines, though the supplied text does not enumerate them [11]. The public API leans the same way, exposing lowercase `string` and `int`, multi-return and `if err != nil`, with `Vec<u8>` and `&str` kept out of signatures [26][27].
Things to watch: whether ownership-based reclamation holds up for the patterns Go programs actually lean on the collector for, such as long-lived channel graphs and escaping closures; whether the provenance CI survives Go 1.26 renumbering the files it cites; and whether the memory figures reproduce outside the author's demo. The project is newly launched and its author warns that details and versions may change [28].