๐ฅ Why Everyone Is Sleeping On TinyGo: Run Go on Microcontrollers and the Web (WASM) Today!
What if I told you that your Go programs could run not only on Linux servers but inside a browser or on a microcontroller smaller than your thumb? Welcome to the world of TinyGo ๐พ.
When you hear "Go," you probably think cloud servers, APIs, or blazing-fast concurrency. But thereโs a lesser-known sibling in the Go ecosystemโand it packs a serious punch in the embedded and WebAssembly (WASM) space. It's called TinyGo, and it's about to blow your dev hat off ๐ฉ๐จ.
In this post, weโre diving deep into:
- What TinyGo is and why it matters.
- Real pain points it solves for embedders and web devs.
- Running Go on an Arduino.
- Compiling Go to WASM thatโs smaller, faster, and install-free.
- Code examples and tips to get you started.
Letโs go (pun intended).
๐ง Wait, What Is TinyGo?
TinyGo is a Go compiler created for resource-constrained environments. While the official Go compiler (gc) is focused on desktop/server environments, TinyGo is designed for microcontrollers and even WebAssembly targets.
It allows you to:
- Write Go code for microcontrollers like Arduino, BBC micro:bit, Raspberry Pi Pico, etc.
- Compile Go into WASM thatโs small enough for frontend production use.
- Share code across embedded and web-based applications (yes, actual code reuse).
๐ฌ Real-World Pain Points It Solves
Pain #1: Embedded Devs Are Still in 1998
If youโve done embedded dev, you're familiar with this:
- Cryptic C/C++ syntax
- 30 minutes to debug a missing semicolon
- Toolchains from the Windows XP era ๐คข
With TinyGo, you get:
- Simple Go syntax
- Modern tooling (VSCode, go fmt, etc.)
- Concurrency via goroutines (yes, it works in TinyGo!)
Pain #2: WebAssembly Builds Are Thick
Go WebAssembly files via the official compiler can be as large as 2MB+.
Thatโs a non-starter for client-side app performance.
TinyGo generates WASM binaries often under 500 KB, sometimes as little as 100 KB depending on the app.
Thatโs a 4โ20x size reduction โฌ
๐ฆพ Code Example: Blink an LED Using Go ๐
Letโs run a Go program on an Arduino (UNO, Nano, or whatever you're using).
โ Prerequisites
- A supported microcontroller (like Arduino Nano with ATmega328P)
- Install TinyGo: https://tinygo.org/getting-started/
brew tap tinygo-org/tools
brew install tinygo
- Install avrdude for flashing Arduino:
brew install avrdude
๐ Connect and Flash
Hereโs our example main.go:
package main
import (
"machine"
"time"
)
func main() {
led := machine.LED
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
for {
led.High()
time.Sleep(time.Millisecond * 500)
led.Low()
time.Sleep(time.Millisecond * 500)
}
}
๐ฅ Compile and Flash to Your Microcontroller
tinygo flash -target=arduino main.go
Boomโyour LED should now be blinking at half-second intervals, using Go.
๐ธ๏ธ Code Example: WebAssembly With Go + TinyGo
Here's a minimal WASM app in Go that runs in the browser:
main.go
package main
import (
"syscall/js"
)
func add(this js.Value, args []js.Value) interface{} {
a := args[0].Int()
b := args[1].Int()
return js.ValueOf(a + b)
}
func main() {
js.Global().Set("add", js.FuncOf(add))
select {} // Keep alive
}
Build for WASM
tinygo build -o add.wasm -target wasm main.go
HTML Interface: index.html
<!DOCTYPE html>
<html>
<body>
<h1>WASM Add in Go</h1>
<button onclick="callAdd()">Add 3 + 4</button>
<p id="result"></p>
<script>
async function init() {
const go = new Go();
const wasm = await WebAssembly.instantiateStreaming(fetch("add.wasm"), go.importObject);
go.run(wasm.instance);
}
function callAdd() {
const result = add(3, 4);
document.getElementById("result").innerText = `3 + 4 = ${result}`;
}
init();
</script>
</body>
</html>
Open in any browserโno server needed. Just serve via a static file server.
Compare WASM Sizes
- Official Go WASM: ~2โ4 MB
- TinyGo WASM: ~150โ300 KB
โ This is production-safe. No more bundling bloated WASM modules.
โ๏ธ Trade-offs: Whatโs the Catch?
- TinyGo doesnโt support the entire Go standard library (yet)
- Runtime behavior is limited (e.g., GC is simple, no reflection)
- You may need to refactor traditional Go code to work
Still, for many constrained environments or WASM work, these are acceptable trade-offs.
โ๏ธ Reuse Code Between Embedded + Web
If youโre building, say, an IoT device and a dashboard:
- Write computation logic in pure Go
- Compile one version for the device (embedded)
- Compile to WASM for the browser
Example: Shared Package
// mathops/math.go
package mathops
func Add(a, b int) int {
return a + b
}
Import into your embedded firmware and also into your WASM frontend.
Thatโs code reuse between hardware and frontend, in Go.
๐ง Final Thoughts: Why TinyGo Is the Hidden Gem
In a world where:
- Embedded development feels ancient
- WebAssembly is gaining traction but has usability barriers
TinyGo is slicing through the noise with a modern, minimal, and cross-domain approach.
Whether you're an embedded dev tired of C/C++ or a frontend junkie exploring WASM, give TinyGo a weekend. You'll be amazed.
โ Ready to Start?
Let me know what you build with it! ๐
If you liked this post, share it or tweet me at @yourhandle. Want a tutorial on TinyGo with Bluetooth or sensor integration? Let me know ๐
๐ ๏ธ If you need help building production-ready applications in TinyGo or shipping WASM-based features to the frontend โ we offer such services.
Top comments (0)