Written by: ekwoster.dev on Thu Sep 18

πŸ”₯ The Hidden Superpowers of TinyGo: How to Run Go Code on Microcontrollers and Beyond!

πŸ”₯ The Hidden Superpowers of TinyGo: How to Run Go Code on Microcontrollers and Beyond!

Cover image for πŸ”₯ The Hidden Superpowers of TinyGo: How to Run Go Code on Microcontrollers and Beyond!

πŸ”₯ The Hidden Superpowers of TinyGo: How to Run Go Code on Microcontrollers and Beyond!

When most developers hear β€œGo”, they think high-performance backend services. When they hear β€œembedded programming”, they think C/C++. But what if I told you that you could write embedded firmware using Go? Welcome to the brave new world of TinyGo β€” the Go that fits into the tiniest chips and also works on the bleeding edge of WebAssembly!

🧠 TL;DR: TinyGo lets you write Go code that compiles down to run on ARM Cortex-M microcontrollers and in the browser using WebAssembly. It’s faster than MicroPython, easier than C, and it’s real, idiomatic Go.

In this post, we're diving deep into TinyGo, uncovering its incredible potential for IoT, edge computing, and WASM. Not only are we going to explore working examples on Arduino and WebAssembly, but we'll also see how TinyGo can be the go-to (pun intended) tool for writing safe, maintainable embedded code without sacrificing performance.


πŸš€ What Is TinyGo?

TinyGo is a Go compiler that targets tiny devices and WebAssembly using LLVM.

  • Supports ARM Cortex-M (e.g., STM32, Arduino Nano 33 IoT)
  • WebAssembly (WASM) that runs in browsers or standalone
  • Esperanto for Go devs entering embedded space

Unlike regular Go, the Go runtime in TinyGo is a tiny subset β€” necessary to keep binaries small (you know, under 32 KB kinda needs that 🀏).


⚑ TinyGo vs. MicroPython vs. C β€” A Quick Showdown

LanguagePerformanceMemory FootprintDev ergonomicsCommunity
C/C++πŸš€πŸš€πŸͺΆ LowestπŸ˜΅β€πŸ’« Steep learningHuge
MicroPython🐌 Slow🧠 Medium😊 EasyGreat
TinyGo⚑ Fast🧠 Low😎 Smooth (Go!)Growing

What's the catch? Not all Go features work (e.g., reflect, interface{} can be limited).


πŸ§ͺ Real Example #1: Blinking an LED on Arduino Nano 33 IoT with TinyGo

Let’s start with a classic: the Blink.

πŸ”§ Requirements

  • Arduino Nano 33 IoT
  • TinyGo installed (https://tinygo.org/getting-started/)

βœ… Code Example (blink.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)
	}
}

πŸ—οΈ Build and Flash

tinygo flash -target=arduino-nano33iot blink.go

And voilΓ  β€” blinking like a champ πŸŽ‰


🧠 Real Example #2: WebAssembly and TinyGo in the Browser

TinyGo compiles to WASM with a much smaller output compared to Go’s default WASM toolchain.

Sample Code (main.go)

package main

import (
	"syscall/js"
)

func main() {
	alert := js.Global().Get("alert")
	alert.Invoke("Hello from TinyGo WASM πŸš€")
}

Build It:

tinygo build -o main.wasm -target wasm main.go

Embed in HTML:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body>
  <script>
    const go = new Go();
    WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then(result => {
      go.run(result.instance);
    });
  </script>
</body>
</html>

πŸ‘‰ When you load the page β€” BAM! Alert pops up from Go-WASM.

πŸ’Ž Real World Usage?

  • Create WASM libraries in Go
  • Replace heavy JavaScript modules with TinyGo-WASM
  • Target both embedded devices and browsers with the same code πŸ”₯

πŸ•ΉοΈ Bonus: Accessing Sensors on Microcontrollers

Let’s read real-world data β€” say from a temperature sensor like the DHT11.

Sample Code:

import (
	"time"
	"machine"
	"tinygo.org/x/drivers/dht"
)

func main() {
	sensor := dht.New(machine.D2, dht.DHT11)
	sensor.Configure()

	for {
		temp, humidity, err := sensor.ReadRetry(10)
		if err == nil {
			println("Temp:", temp, "Β°C",
				" Humidity:", humidity, "%")
		}
		time.Sleep(time.Second * 2)
	}
}

Build and flash again β€” now your Go code reads real-world data ✨


🧠 Why TinyGo Matters

Let’s break the paradigm:

  • Go is safe, typed, and modern
  • Embedded dev is bug-prone, manual, and niche
  • TinyGo bridges them β€” making embedded and web apps safer and more accessible

πŸ’‘ Use TinyGo to write libraries usable across:

  • A microcontroller firmware (e.g. Arduino)
  • A browser via WebAssembly
  • A command-line diagnostic tool (std Go)

πŸ‘·β€β™‚οΈ What's Missing?

  • Third-party libraries + driver support is growing but less than C or MicroPython
  • No net/http unless you're on appropriate targets
  • Async concurrency and goroutines are limited (but supported)

Contribute and grow the ecosystem if you love Go!


🚨 Final Verdict: Use Cases in the Wild

Use CaseWhy TinyGo?
IoT Device SDKsOne codebase for browser + device testing
Plants watering systems 🌿Go + DHT + Servo control
WASM-Libs for JavaScriptReplace bloated JS with tiny fast WASM
EdTech for kidsEasier than C, stronger than MicroPython
Low-power WearablesLong battery life with low memory footprint

πŸ“Ž Resources


♻️ Wrapping Up

TinyGo is not here to β€œreplace C”. It’s here to open doors. If you love Go, and you want to get your hands dirty in hardware or compile blazing fast WebAssembly apps, give TinyGo a try.

Don’t just code APIs. Build electric cats. Laser bots. Air-qual sensors in your kitchen. And make the browser do what JS never could.

Go tiny β€” think big.

Are you using TinyGo in production? Got questions about drivers or WebAssembly? Share them in the comments below!


✨ If you're exploring embedded Go or experimenting with TinyGo + WASM for real-world applications β€” we offer tailored research and development services to support your innovation!