TinyGo
2018TinyGo is a Go compiler for small places. It's designed to bring the Go programming language to microcontrollers, WebAssembly, and other environments where traditional Go is too resource-intensive.
About TinyGo
TinyGo is not just a subset of Go - it's a completely different compiler implementation built on LLVM that targets small devices and embedded systems. While regular Go is excellent for servers and desktop applications, TinyGo excels in:
- Microcontrollers: Arduino, Raspberry Pi Pico, micro:bit, ESP32, and many others
- WebAssembly: Creating small, fast WASM modules
- Embedded Systems: IoT devices, sensors, and real-time applications
- Static Binaries: Producing tiny, statically linked executables
Key Differences from Regular Go
Smaller Runtime
TinyGo implements a much smaller runtime compared to standard Go:
- No garbage collector (or a very minimal one depending on target)
- Smaller standard library footprint
- Direct hardware access for microcontrollers
Size Comparison
Where a regular Go "Hello World" might be 2MB+, TinyGo can produce:
- Microcontrollers: 1-10KB depending on target
- WebAssembly: 1-50KB
- Linux executables: 10-100KB
Compilation Targets
TinyGo supports dozens of microcontroller targets out of the box:
# Examples of supported targets
tinygo flash -target=arduino main.go
tinygo flash -target=microbit main.go
tinygo flash -target=pico main.go
tinygo build -target=wasm main.goLanguage Features
TinyGo supports most Go language features including:
- Goroutines (limited on some targets)
- Channels
- Interfaces
- Closures
- Most standard library packages (subset)
Note: Some advanced features like reflection and the full net/http package may not be available on all targets.
Real-World Applications
TinyGo is used in production for:
- IoT Sensors: Temperature, humidity, motion sensors
- Robotics: Motor controllers, sensor integration
- Wearables: Fitness trackers, smartwatches
- Industrial Control: PLCs, automation systems
- Edge Computing: Lightweight data processing
Development Workflow
Unlike regular Go development, TinyGo often involves:
- Target Selection: Choosing your hardware platform
- Hardware Abstraction: Using machine package for GPIO, I2C, SPI
- Size Optimization: Keeping code minimal for resource constraints
- Cross-Compilation: Building for different architectures
Example microcontroller code:
package main
import (
"machine"
"time"
)
func main() {
led := machine.LED
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
for {
led.High()
time.Sleep(500 * time.Millisecond)
led.Low()
time.Sleep(500 * time.Millisecond)
}
}Further Exploration
- Official Website: tinygo.org
- GitHub Repository: github.com/tinygo-org/tinygo
- Hardware Drivers: tinygo.org/x/drivers
- Examples: github.com/tinygo-org/tinygo/tree/release/src/examples
- Supported Boards: tinygo.org/docs/reference/microcontrollers/
TinyGo opens up the world of embedded programming to Go developers, bringing familiar syntax and powerful features to the smallest of devices.
Hello World
package main
// BEGIN_FRAGLET
import "fmt"
func main() {
fmt.Println("Hello World!")
}
// END_FRAGLETCoding Guide
Language Version
TinyGo 0.38.0 (Go subset)
Execution Model
- Compiled language using
tinygo build - Code is compiled to a binary, then executed
- Standard Go execution model with
main()function inmainpackage - TinyGo is a subset of Go optimized for small targets (microcontrollers, WebAssembly, etc.)
Key Characteristics
- Statically typed (Go subset)
- Case-sensitive (exported identifiers start with uppercase)
- Garbage collected
- Strong typing with type inference (
:=operator) - Package-based module system
- Built-in concurrency primitives (goroutines, channels) - limited support
- No classes (uses structs and methods instead)
- Functions are first-class citizens
- Important: TinyGo supports a subset of Go's standard library and features
Fragment Authoring
Write valid TinyGo code. The package main declaration is pre-provided. Your fragment should include import declarations and define func main() as the entry point.
Available Packages
The template includes the standard library package:
fmt- Formatted I/O (Println, Printf, Sprintf)
Additional standard library packages may be available (TinyGo subset):
strings- String manipulationstrconv- String conversionsos- Operating system interface (limited)math- Mathematical functionstime- Time operations (limited)sync- Synchronization primitives (limited)
Note: TinyGo supports a subset of Go's standard library. Some packages and features may not be available.
Common Patterns
- Print:
fmt.Println("message")orfmt.Printf("format %s\n", value) - Variables:
var x int = 10orx := 10(type inference) - Functions:
func add(a, b int) int { return a + b } - Structs:
type Person struct { Name string; Age int } - Methods:
func (p Person) String() string { return fmt.Sprintf("%s (%d)", p.Name, p.Age) } - Slices:
numbers := []int{1, 2, 3}ornumbers := make([]int, 0, 10) - Maps:
m := make(map[string]int)orm := map[string]int{"a": 1} - Basic loops:
for i := 0; i < 10; i++ { ... }orfor _, num := range numbers { ... }
Examples
// Simple output
func main() {
fmt.Println("Hello from fragment!")
}
// Variables and calculations
func main() {
a := 5
b := 10
fmt.Printf("Sum: %d\n", a+b)
}
// Functions
func add(a, b int) int {
return a + b
}
func main() {
result := add(5, 10)
fmt.Printf("5 + 10 = %d\n", result)
}
// Slices and loops
func main() {
numbers := []int{1, 2, 3, 4, 5}
sum := 0
for _, num := range numbers {
sum += num
}
fmt.Printf("Sum: %d\n", sum)
}
// Structs and methods
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s is %d years old", p.Name, p.Age)
}
func main() {
p := Person{Name: "Alice", Age: 30}
fmt.Println(p)
}
// Maps
func main() {
m := map[string]int{
"apple": 5,
"banana": 3,
}
fmt.Printf("Apples: %d\n", m["apple"])
}
// String operations
func main() {
s := "Hello"
s += " World!"
fmt.Println(s)
fmt.Printf("Length: %d\n", len(s))
}Caveats
- Fragments must be valid TinyGo code that compiles
- TinyGo supports a subset of Go - some Go features may not be available
- Remember that exported identifiers (functions, types, variables) must start with uppercase
- Variables declared with
:=must be used (Go doesn't allow unused variables) - The code is compiled fresh each time, so compilation errors will fail execution
- TinyGo has limited support for some standard library packages
- Slices are reference types, maps are reference types
- Zero values:
0for numbers,""for strings,nilfor pointers/slices/maps/channels - Goroutines and channels have limited support in TinyGo compared to full Go