Google-sponsored TinyGo is a new LLVM-based Go compiler to make it possible to run Go programs on microcontrollers, including the Arduino Uno, Arduino Nano33 IoT, and the BBC micro.bit, as well as modern browsers using Web Assembly.
TinyGo strives to create as small a binary as possible and attempts to optimize for memory usage. In contrast, Go compiler is optimized for speed. TinyGo also uses its own runtime, which is smaller than Go's.
The original reasoning was: if Python can run on microcontrollers, then certainly Go should be able to run on even lower level micros.
TinyGo does not aim to be able to compile any possible Go program, rather to compile most Go programs without modifications. Most language features are supported, including slices, interfaces, closures and bound methods. Others may be partially supported. In particular, since most targeted microcontrollers are single-core, goroutines are not optimized; reflection is available for most common types like number, strings, and structs. Maps are limited to using a reduced set of types such as strings, integers, and pointers as map keys. Furthermore, performance may be subpar.
The following is a program to blink a LED on any of the supported microcontrollers:
package main
import (
"machine"
"time"
)
func main() {
led := machine.LED
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
for {
led.Low()
time.Sleep(time.Millisecond * 1000)
led.High()
time.Sleep(time.Millisecond * 1000)
}
}
Possibly the most striking feature of TinyGo is its attempt to maintain Go memory model, which requires some sort of garbage collection support. TinyGo uses a simple conservative mark-sweep collector. Collection is triggered when the heap is exhausted, which can be determined at compile time, or when the developer calls runtime.GC()
. TinyGo also provides some support to optimize memory usage by inspecting where memory allocation actually happens in a program. This can be useful to avoid memory allocations in main loops.
As mentioned, TinyGo targets WASM as well. Although the official Go compiler can compile to WASM, TinyGo is able to provide a much smaller output. According to Google, it is not uncommon for the Go compiler to generate WASM files of 10+ MB when importing libraries, with ~2MB being the minimum. Instead, a simple "hello world" program is translated into a 575 bytes WASM program by TinyGo.
TinyGo can run on Linux, macOS, and Windows. A Docker image is also available to simplify its installation.