DEV Community

Cover image for What No One Tells You About TinyGo: Running Go on an Arduino Changed How I Think About Embedded Programming
Yevhen Kozachenko 🇺🇦
Yevhen Kozachenko 🇺🇦

Posted on • Originally published at ekwoster.dev

What No One Tells You About TinyGo: Running Go on an Arduino Changed How I Think About Embedded Programming

What No One Tells You About TinyGo: Running Go on an Arduino Changed How I Think About Embedded Programming

When I first heard about TinyGo, I thought: “Cool, Go for microcontrollers... I doubt it’s practical.” Fast forward a month, and I’m blinking LEDs and handling button inputs with Go on my Arduino Uno — and loving every minute of it.

This blog post isn't just another overview — I'm diving deep into what it's actually like to work with TinyGo, what problems it solves (and doesn't), and how it changes the way you can think about embedded systems development. I'll walk you through a complete example with real code, compare the experience to classic Arduino C/C++, and share how switching to Go on microcontrollers made me a better developer both in the embedded world and fullstack web development.

🧠 Why TinyGo Is a Game-Changer

Let’s set the scene.

Traditionally, embedded programming means clunky C code, opaque compilers, memory juggling, and lots of trial and error. Yes, it’s powerful, but the learning curve is steep and debugging is often a form of digital voodoo.

Here’s why TinyGo flips that on its head:

  • ✅ Type safety and powerful tooling from Go
  • ✅ No garbage collection overhead at runtime (TinyGo uses escape analysis to include the smallest possible runtime)
  • ✅ Works on Arduino, ESP32, BBC micro:bit, and WebAssembly
  • ✅ Compiles blazing fast compared to gcc toolchains

As a developer who is also working in web backend systems using Go, being able to reuse knowledge in the embedded space is cosmic-level productivity alignment.

🤯 Real World: Blinking an LED with Button Input in Go

Let’s look at how the same behavior (toggle an LED with a button press) is written in C vs Go.

🤢 The C Way (Traditional Arduino)

const int buttonPin = 2;
const int ledPin = 13;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  int buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }
}
Enter fullscreen mode Exit fullscreen mode

😍 The TinyGo Way

package main

import (
    "machine"
    "time"
)

func main() {
    led := machine.LED
    button := machine.D2   // pin 2

    led.Configure(machine.PinConfig{Mode: machine.PinOutput})
    button.Configure(machine.PinConfig{Mode: machine.PinInput})

    for {
        if button.Get() {
            led.High()
        } else {
            led.Low()
        }
        time.Sleep(10 * time.Millisecond)
    }
}
Enter fullscreen mode Exit fullscreen mode

What do you notice?

  • The structure is cleaner, type-checked, and takes advantage of Go’s standard libraries.
  • No main() void awkwardness — the structure feels like writing any regular Go CLI app.

🔧 How to Get Started

Setting up TinyGo is surprisingly smooth.

Step 1: Install TinyGo

brew tap tinygo-org/tools
brew install tinygo
Enter fullscreen mode Exit fullscreen mode

Or grab it from the official downloads.

Step 2: Install AVR tools (for Arduino Uno)

brew install avr-gcc
Enter fullscreen mode Exit fullscreen mode

Step 3: Write Your .go File (like above)

Step 4: Compile and Flash

tinygo flash -target=arduino uno-led-blink.go
Enter fullscreen mode Exit fullscreen mode

Your Arduino will restart and start running your compiled Go program! Yes — you’re running freaking statically compiled Go code on an 8-bit microcontroller!

📊 TinyGo’s Secret Weapon: Code Size

Compare these code sizes:

  • Arduino C++ binary for our LED app: ~3.2 KB
  • TinyGo binary for same app: ~2.4 KB

How? TinyGo aggressively compiles only used packages/functions (leveraging Go's linker and escape analysis). And it's not some kind of toy language runtime — apps scale as you'd expect.

🚀 Advanced: Using TinyGo with WebAssembly

That same Go code can be compiled and run in the browser. Don’t believe me?

tinygo build -o main.wasm -target wasm yourfile.go
Enter fullscreen mode Exit fullscreen mode

Then serve it using a web app and call Go functions from your JavaScript glue code. Same syntax, shared logic. It’s a dream come true for teams building fullstack web apps with heavy IOT integrations.

TinyGo opens the door to fully isomorphic Go codebases, spanning browser apps, backend REST services, and tiny embedded devices.

🛑 Watch Out: Language Limitations

TinyGo isn’t a full Go implementation — it supports a major (and growing) subset of features:

  • No reflection
  • No interface{} (not yet robust, mostly for simple uses)
  • No goroutines on most targets (they compile but run sequentially)
  • No map support in many cases

But you still get:

  • Great error handling (if err != nil)
  • Type-safe APIs
  • Structs and modules
  • Hardware abstraction for GPIO, I2C, SPI, UART, etc

🙌 Why Use TinyGo Over MicroPython or Arduino C?

Let's be honest, MicroPython is great — but performance is lacking. You don’t want to run real-time sensor loops with tight timing on a MicroPython interpreter.

Arduino C is fast, but unstructured, especially for larger programs.

TinyGo gives you:

Feature Arduino C MicroPython TinyGo
Type Safe
Compile Speed 😐 ✅ (none)
Performance
WebAssembly
Modern Syntax

🧠 Final Verdict: Is TinyGo Worth It?

Absolutely — if you:

  • Already use Golang and want to go to hardware
  • Want safer, more maintainable embedded projects
  • Hate thinking about pointers and memory management in C
  • Want multiple target platforms (microcontrollers, browsers, servers)

TinyGo is not just a developer toy — it’s a serious rethink in how we approach embedded development. It’s about time we started seeing microcontrollers as part of the modern dev stack, not some archaic island.

🔮 Bonus: Hardware You Can Use with TinyGo

  • Arduino Uno
  • ESP32/ESP8266
  • Raspberry Pi Pico (RP2040)
  • BBC micro:bit
  • Adafruit Circuit Playground
  • STM32 chips
  • And more…

See the full TinyGo supported hardware list here.

🧪 Try it Now

Don’t just read this — write your first blinking LED in Go! It’ll change how you view the boundary between software and hardware.

Happy hacking!


💡 If you need help with bringing your idea to life or building embedded and web connected products using Go – we offer fullstack development.

Top comments (3)

Collapse
 
zanzythebar profile image
DaOfficialWizard • Edited

Embedded engineer here, I really wanted to like this article. I just can't. Not only is a lot of it factually incorrect, but the blatant and obvious use of ChatGPT is ... telling.

Arduino C is not a thing. Arduino is a C++ 11 library that wraps the internal tooling of the target architecture. C is largely type safe, not any less or more than Go. Both of them are type checked at compile type (sure you have void * and casting in C ... same for Go just different syntax). Types, fundamentally are a memory-layout concept. Types are not real things.

I love tiny go, however it has significant GC overhead on a resource constrained platform. Clean compile C++ or C will always outperform it. Smaller binaries, no GC bloat, full control over the runtime, advantage of compiler and platform tooling optimizations ... etc.

Lastly, C not being fit for large projects?! You've got to be kidding, right? It's the defacto for all operating systems. The linux kernel has over 1M LOC in pure C. C is great for structured projects. Not to mention, all interpreters are written in C, even python. I would consider those large projects. The browser engine that I am using to make this rant ... written predominantly in C & C++.

I am really happy that you are having fun and wanting to share with the wider community ... but if you are trying to educate others, please put in a little bit more quality control.

Collapse
 
ekwoster profile image
Yevhen Kozachenko 🇺🇦

Thanks for the detailed feedback! You’re absolutely right about Arduino being C++ under the hood, and I should’ve been more precise in how I phrased that. My goal wasn’t to dismiss C/C++ (which are obviously the backbone of embedded systems) but to share how TinyGo felt refreshing coming from a Go/web background. I’ll tighten up the technical accuracy in future posts — appreciate you pointing it out.

Collapse
 
leena_malhotra profile image
Leena Malhotra

Running Go on an Arduino isn’t just a hack. It forces you to rethink constraints, and that’s where real engineering clarity comes from.