Written by: ekwoster.dev on Tue Aug 12

Getting Started with TinyGo: Bringing Go to Microcontrollers and WebAssembly

Getting Started with TinyGo: Bringing Go to Microcontrollers and WebAssembly

Cover image for Getting Started with TinyGo: Bringing Go to Microcontrollers and WebAssembly

Getting Started with TinyGo: Bringing Go to Microcontrollers and WebAssembly

Go (or Golang) has taken the software development world by storm thanks to its simplicity, performance, and concurrency model. But traditionally, Go was intended for server-side development — not for systems with constrained resources or compiling to WebAssembly (Wasm). Enter TinyGo – a Go compiler that allows developers to write code for microcontrollers and to web-optimized formats like Wasm.

In this article, we will explore TinyGo, understand how it works, and walk through some practical examples targeting both microcontrollers and the web using WebAssembly.


What is TinyGo?

TinyGo is a project that aims to bring Go to embedded systems and WebAssembly. As its name suggests, it is a small Go compiler based on LLVM. TinyGo is designed to support:

  • Microcontrollers (e.g., Arduino, BBC micro:bit, Adafruit Circuit Playground)
  • WebAssembly (for compiling Go code to run in browsers or edge environments)
  • Command-line tools and small applications requiring low memory overhead

Key Features:

  • Small binary outputs ideal for embedded environments.
  • Compatibility with many Go standard packages.
  • LLVM backend that helps with performance and portability.

Why Use TinyGo?

The usual Go compiler (gc) generates binaries optimized for performance, but the tradeoff is in memory usage and binary size. For constrained devices like the Atmega328p found in an Arduino Uno, this is a non-starter. TinyGo addresses this by outputting minimal binary sizes and leveraging LLVM optimizations.

Benefits include:

  • Running Go on microcontrollers.
  • Writing Go code for browser applications using WebAssembly.
  • Easier learning curve for developers already comfortable with Go.
  • Leverages Go’s syntax and built-in concurrency (though with some limitations in TinyGo).

Installing TinyGo

Before we can build anything with TinyGo, we need to install it.

Step 1: Install Go

You’ll need Go 1.20 or higher. Get it from: https://golang.org/dl/

Step 2: Install TinyGo

Follow these platform-specific instructions:

macOS (using Homebrew):

brew tap tinygo-org/tools
brew install tinygo

Ubuntu/Debian-based Linux:

wget https://github.com/tinygo-org/tinygo/releases/download/v0.30.0/tinygo_0.30.0_amd64.deb
sudo dpkg -i tinygo_0.30.0_amd64.deb

Windows:

Download the appropriate installer from the TinyGo GitHub Releases page and follow the instructions.


First TinyGo Program for Arduino

Let’s write a simple Blink program to flash an LED on an Arduino Uno board:

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)
    }
}

Flashing the Program

Make sure your Arduino Uno is connected, then run:

tinygo flash -target=arduino blink.go

Voila! You should see the onboard LED blinking.


Compiling to WebAssembly (Wasm)

TinyGo can also compile to WebAssembly, making it great for web apps and browser-based games.

Let’s look at a basic Wasm example:

package main

import (
    "fmt"
    "time"
    "syscall/js"
)

func main() {
    js.Global().Set("greet", js.FuncOf(greet))
    select {} // block forever
}

func greet(this js.Value, args []js.Value) interface{} {
    name := args[0].String()
    greeting := fmt.Sprintf("Hello, %s! The time is %s", name, time.Now().Format(time.RFC822))
    js.Global().Call("alert", greeting)
    return nil
}

Compiling:

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

HTML to load it:

<!DOCTYPE html>
<html>
<head><title>TinyGo Wasm</title></head>
<body>
    <h1>TinyGo WebAssembly</h1>
    <button onclick="greet('TinyGo Dev')">Say Hello</button>
    <script src="wasm_exec.js"></script>
    <script>
        const go = new Go();
        WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then(result => {
            go.run(result.instance);
        });
    </script>
</body>
</html>

Limitations of TinyGo

While TinyGo is powerful, there are some trade-offs to be aware of:

  • Some parts of the Go standard library aren’t supported.
  • Limited support for goroutines (heavily simplified threading model).
  • Not all architectures and boards are supported yet.
  • Debugging tooling is still developing.

That said, the project is actively evolving and its community is growing rapidly.


Use Cases for TinyGo

TinyGo opens up new possibilities for Go developers:

  1. IoT Projects: Build smart devices, sensors, and controllers in Go.
  2. Edge Computing: Run Go on edge servers using WebAssembly.
  3. Educational Projects: Students can prototype microcontroller projects using an easier language than C/C++.
  4. Wasm Web Apps: Integrate back-end logic directly in the web interface using Go.

Resources & Community

Getting involved with the TinyGo community is easy:

  • Website: https://tinygo.org
  • GitHub: https://github.com/tinygo-org/tinygo
  • Discord & Forums: Great places to ask questions and contribute.

Conclusion

TinyGo brings the power and elegance of Go to resource-constrained environments and the front-end via WebAssembly. Whether you’re building a blinking LED on an Arduino or an interactive app in your browser, TinyGo enables you to stay within the Go ecosystem.

As embedded devices and WebAssembly grow in popularity, tools like TinyGo may become an integral part of every full-stack developer’s toolkit.

So why not try TinyGo for your next project and explore new horizons in embedded and web development — all with the language you already love?

Stay curious, and happy coding! 🚀

💡 If you're exploring TinyGo for embedded or web-based applications and need help with full stack integration, we offer such services: https://ekwoster.dev/service/fullstack-development