[HN Gopher] Go on Embedded Systems and WebAssembly
___________________________________________________________________
Go on Embedded Systems and WebAssembly
Author : uticus
Score : 200 points
Date : 2026-04-03 16:57 UTC (1 days ago)
(HTM) web link (tinygo.org)
(TXT) w3m dump (tinygo.org)
| nasretdinov wrote:
| Tinygo made a lot of progress over the years -- e.g. they've
| recently introduced macOS support!
|
| It does indeed produce much smaller binaries, including for
| macOS. yuriy@MacBookAir ~/t/tinygo> time tinygo
| build -o test-tiny main.go
| ________________________________________________________
| Executed in 1.06 secs fish external usr
| time 1.18 secs 0.31 millis 1.18 secs sys time
| 0.18 secs 1.50 millis 0.18 secs
| yuriy@MacBookAir ~/t/tinygo> time go build -o test-normal main.go
| ________________________________________________________
| Executed in 75.79 millis fish external
| usr time 64.06 millis 0.41 millis 63.64 millis
| sys time 96.76 millis 1.75 millis 95.01 millis
| yuriy@MacBookAir ~/t/tinygo> ll total 5096 -rw-r--
| r--@ 1 yuriy staff 74B 3 Apr 19:17 main.go -rwxr-xr-x@
| 1 yuriy staff 2.3M 3 Apr 19:18 test-normal* -rwxr-xr-x@
| 1 yuriy staff 192K 3 Apr 19:18 test-tiny*
| yuriy@MacBookAir ~/t/tinygo> cat main.go package main
| import "fmt" func main() {
| fmt.Printf("Hello world!\n") }
| maccard wrote:
| What does it look like if you pass -ldflags="-s -w"?
| guessmyname wrote:
| With Go v1.26.1 package main import
| "fmt" func main() { fmt.Printf("Hello
| World!\n") }
|
| Binary sizes:
|
| * 2581616B (2.5MB) - 1714560B (1.6MB) (with -ldflags="-s -w")
|
| * 1531920B (1.5MB) - 753680B (0.7MB) (with upx --force-macos)
|
| That said, a trivial "Hello World!" isn't a meaningful
| benchmark. If you're going to play that game, you might as
| well swap `fmt.Printf` for `fmt.Println`, or even `println`
| to avoid the import statement entirely. At that point, you're
| no longer comparing anything interesting, the binaries end up
| roughly the same size anyway.
| tatjam wrote:
| Writing embedded code with an async-aware programming language is
| wonderful (see Rust's embassy), but wonder how competitive this
| is when you need to push large quantities of data through a micro
| controller, I presume this is not suitable for real-time stuff?
| nasretdinov wrote:
| You can disable GC in tinygo, so if you allocate all the
| necessary buffers beforehand it can have good performance with
| real-time characteristics. If you _need_ dynamic memory
| allocation then no, because you need GC it can't provide
| realtime guarantees.
| Groxx wrote:
| Doesn't seem like those should be mutually exclusive, though
| the habits involved are quite opposing and I can definitely
| believe they're _uncommon_.
|
| E.g. GC doesn't need to be precise. You could reserve CPU
| budget for GC, and only use that much at a time before
| yielding control. As long as you still free enough to not
| OOM, you're fine.
| carverauto wrote:
| We're streaming RSTP camera feeds through WASM plugins and
| host-bridge adapters, no problem. I was surprised how well it
| worked TBH.
|
| https://code.carverauto.dev/carverauto/serviceradar/src/bran...
| clktmr wrote:
| I've written a fair amount of code for EmbeddedGo. Garbage
| Collector is not an issue if you avoid heap allocations in your
| main loop. But if you're CPU bound a goroutine might block
| others from running for quite some time. If your platform
| supports async preemption, you might be able to patch the
| goroutine scheduler with realtime capabilities.
| randusername wrote:
| Can you elaborate on this and how it would be different from
| signaling on interrupts and DMA?
|
| Hardware-level async makes sense to me. I can scope it. I can
| read the data sheet.
|
| Software async in contrast seems difficult to characterize and
| reason about so I've been intimidated.
| jamesmunns wrote:
| It's really not so different! In embassy, DMA transfers and
| interrupts become things that you can .await on, the process
| is basically: * The software starts a
| transaction, or triggers some event (like putting data in the
| fifo) * The software task yields * When the "fifo
| empty" interrupt or "dma transfer done interrupt" occurs, it
| wakes the task to resume * the software task checks if
| it is done, and either reloads/restarts if there's more to
| do, or returns "done"
|
| It's really not different than event driven state machines
| you would have written before, it's just "in-band" of the
| language now, and async/await gives you syntax to do it.
|
| Even if you don't know Rust, I'd suggest poking around at
| some of the examples here:
|
| https://github.com/embassy-rs/embassy/tree/main/examples
|
| And if you want, look into the code behind it.
| soypat wrote:
| It is more performant than rust but less performant than Zig
| when not doing GC heavy stuff. https://github.com/tinygo-
| org/tinybench
| carverauto wrote:
| We're using TinyGo and the Wazero runtime for our WASM plugin
| system in ServiceRadar, highly recommend both if you're using
| golang.
| evacchi wrote:
| Yay wazero maintainer here, thanks for the shout-out!
| pancsta wrote:
| It was good to meet at wasm.io!
| apitman wrote:
| Wazero is awesome. For anyone wanting to embed in languages
| other than Go, check out Extism.
| mi_lk wrote:
| What are the tradeoffs compared to standard Go?
| jrockway wrote:
| It gets better every release, but there are missing language
| features:
|
| https://tinygo.org/docs/reference/lang-support/
|
| And parts of the stdlib that don't work:
|
| https://tinygo.org/docs/reference/lang-support/stdlib/
| pancsta wrote:
| TinyGo doesnt have networking in WASI[0] and the WASM websocket
| module[1] was last updated 5 years ago. Go without stdlib is not
| Go.
|
| [0] https://github.com/tinygo-org/tinygo/issues/4880
|
| [1] https://github.com/Nerzal/tinywebsocket
| dkegel wrote:
| For embedded systems, see https://github.com/tinygo-org/net
|
| For WASI, check out WASI Preview 2,
| https://docs.wasmtime.dev/api/wasmtime_wasi/p2/index.html
| pancsta wrote:
| Thats the host, but the guess is missing, as stated in the
| issue last year "I guess we could add sockets to wasip2". To
| be honest, even BigGo failed me on websocket conns on both
| wasmtime and wazero (connects and gets into an inf loop on
| reply). WebWorkers and GOOS=js work like a charm tho on BigGo
| in FF/chrome.
| dkegel wrote:
| Yeah, I suspect sockets in wasip2, and wasip2 in general,
| are just now having the bugs shaken out of them.
|
| The company I work for is just now upgrading its edge WASI
| support to wasip2.
| pjmlp wrote:
| Interestingly enough for the C and C++ folks, compiler specific
| dialects for embedded without standard library, are still
| argued for as if being C and C++.
| jackhalford wrote:
| Could we compile tailscale with tinygo to run it on openwrt? Last
| time I checked tailscale was too large for 8MB flash routers
| mayama wrote:
| Lot of stdlib, especially net, crypto, in tinygo doesn't
| compile, or if compiles has stubs as implementation that panics
| with not implemented. Few years ago, I tried compiling small
| terminal http client app and failed at compile stage.
|
| https://tinygo.org/docs/reference/lang-support/stdlib/
| febed wrote:
| Does it support ESP32
| kitd wrote:
| Full list is here:
|
| https://tinygo.org/docs/reference/microcontrollers/
|
| A few ESP32s on there.
| dkegel wrote:
| Another one was added an hour ago, https://github.com/tinygo-
| org/tinygo/pull/5280
| ghoul2 wrote:
| Its a fantastic project, but seems almost inactive now. I have a
| tiny PR pending for weeks, even reviewed, but not merged. I have
| another patch I have not submitted as I want to first navigate
| the earlier PR to completion. Both were bugs that bit me, and I
| ended up wasting quite a lot of time trying to find it:
|
| 1. go:embed supports "all:<pattern" while tinygo silently ignore
| it. I ripped my hair out trying to figure out why my files were
| not showing up in embedfs. PR pending.
|
| 2. go allows setting some global vars at the build cli (think
| build version/tag etc). In the code, one can define a default,
| and then the value provided (if any) on the cli can override it
| at build time. Tinygo fails to override the value at build-time,
| silently, if a default value is provided for the var in code.
| This PR I have not submitted yet, as its more intrusive.
|
| I hope it picks up steam again soon. I love using go for embedded
| and CF worker use and tinygo makes both of these use cases much
| more viable than regular go. Honestly, I hope tinygo can be
| rolled over into the main go toolchain as "target arch".
| justinclift wrote:
| Looking at the commit history, it seems pretty active:
|
| https://github.com/tinygo-org/tinygo/commits/dev/
|
| Maybe the opposite thing is happening, whereby the maintainers
| are getting overwhelmed?
| soypat wrote:
| It'd be nice to get some help :) TinyGo developers are
| community driven as we receive no financing.
| dkegel wrote:
| FWIW the company I work for has been helping out a little
| here and there, one of our engineers has four commits in so
| far this year.
| dkegel wrote:
| There have been four committers in the last week, so it's
| active!
|
| Consider joining the slack channel #tinygo-dev on
| gophers.slack.com and pinging them about the PR.
| rcarmo wrote:
| TinyGo was instrumental in getting https://github.com/rcarmo/go-
| rdp to work. It generates very tight, pretty high performing
| WASM, and that allowed me to push all the RDP decoding to the
| browser side while making sure I had a sane test suite. Heartily
| recommended.
___________________________________________________________________
(page generated 2026-04-04 23:01 UTC)