When you’re programming microcontrollers, you’re likely to think in C if you’re old-school, Rust if you’re trendy, or Python if you want it done quick and have resources to spare. What about Go? The programming language, not the game. That’s an option, too, with TinyGo now supporting over 100 different dev boards, along with webASM.
We covered TinyGo back in 2019, but they were just getting started at that point, targeting the Arduino and BBC:micro boards. They’ve grown that list to include everything from most of Adafruit’s fruitful suite of offerings, ESP32s, and even the Nintendo Game Boy Advance. So now you can go program go in Go so you can play go on the go.
The biggest drawback–which is going to be an absolute dealkiller for a lot of applications–is a lack of wireless connectivity support. Claiming to support the ESP8266 while not allowing one to use wifi is a bit of a stretch, considering that’s the whole raison d’être of that particular chip, but it’s usable as a regular microcontroller at least.
They’ve now implemented garbage collection, a selling point for those who like Go, but admit it’s slower in TinyGo compared to its larger cousin and won’t work on AVR chips or in WebAssembly. It’s still not complete Go, however, so just as we reported in 2019, you won’t be able to compile all the standard library packages you might be used to. There are more of them than there were, so progress has been made!
Still, knowing how people get about programming languages, this will please the Go fanatics out there. Others might prefer to go FORTH and program their Arduinos, or to wear out their parentheses keys with LISP. The more the merrier, we say!

“When you’re programming microcontrollers, you’re likely to think in C if you’re old-school”, ahh no, I’d be thinking assembler. For some microcontrollers, I still work in assembler.
Yep, if you want bulletproof in a hostile environment it’s probably 8048 or 8051, and you absolutely can’t use the timers and interrupts effectively without assembly. For some apps (not even all of them video games) even the 8080, Z80, 6809, and of course 6502 require cycle counting. You can make C work on a stackless machine like an 1802 or Parallax P1, but there are other ways to torture yourself that are more fun. And embedded 8-bit cores are used everywhere because they’re crazy cheap add-ons for hardware controllers.
But if you look at the list of supported boards you see a lot of ARM based boards like the PICO boards and such. In that case ‘C’ would be something you’d think of :) . That said, back to some ‘C’ programming tonight… GO just doesn’t ‘feel’ right the last time I tried to use it. As said above, go with the programming languages that work for you. Assembly, C, and Python work well for me.
heh i came to write this same comment. For something like a PIC12/PIC16 or even its larger “almost has a real stack” cousin, the PIC18, i would still only write in ASM. I actually invented a pidgin forth that is really just a macro assembler, but still…i want to control every resource use, i want to count every cycle, etc. Just a ton of different limitations on the PIC that make C unrealistic.
So that’s my ‘old school’ technique….my new technique, which i’ve only come to accept in the last couple years and have barely written anything using it, is to use C for STM32 / RP2040 class microcontrollers. 32-bit ARM instructions, measurable quantities of RAM and Flash, fast enough that counting cycles is rarely necessary, a cache architecture to where it’s sometimes hard to count cycles accurately, just a bunch of things push me away from my old penny-pincher approach.
But the real thing that pushed me over the edge to accept C on micros was the realization that i don’t need to use some awful SDK. I can make my own “crt” / bootloader in just a few lines of C, and it is enough to initialize like .bss / .data. I do all my own I/O, and micro-managing interrupts and peripherals is just as easy as ASM. Wow!
Nothing against Go, but i can’t see myself personally using something like that for embedded. I’m sure it’s great for some people, for some projects.
OK, that’s the real old school. Kudos for keeping it up! Which ones, may I ask? 8051?
Ought to get around to writing a TCL interp for AVRs. 12 rules, a few base procedures, and you’ve got the whole language.
I am not here to yuck someone’s yum. If you want to write Go on a microcontroller go for it.
But Go without a GC? Just write C. Or write C++ Arduino style. I don’t see any appeal. Circuitpython makes more sense to me, it’s at least hiding some complexity.
Go, so far as I know, doesn’t have any undefined behaviour – in fact I think it’s always very well defined, especially in TinyGo. (The garbage collector might sometimes be a bit unpredictable, but even it should still have well defined behaviour overall.)
Also the Go compiler is lightning fast and all the rest of the toolchain is light years ahead of almost every other language.
For microcontrollers compilation speed is pretty silly though right? At most you can only write a handful of kilobytes of code. Even a slow compiler will be fast enough for any reasonable person.
I don’t understand how Go maintains memory safety guarantees without a GC? If you never deallocate then you either run out of memory or you go straight to UB? If the programmer has to malloc themselves then it’s the same guarantees as C? I think I am confused
When you’re senior and an experienced coder, it’s easy to think everyone can just pick up another language. Just get immersed in it.
But not everyone is able to do that. Not everyone senior is an experienced coder. There are a lot of people doing jobs with Go. People want to get away from Python, especially at work. The idea a part-time hobbyist should become proficient in C or Rust is discouragement.
TinyGo can now compile to bare metal and execute without an OS. And sure, it is not the best tool for embedded, but then again neither was Arduino.
At some point we’ll just be coding this stuff with an LLM and letting it choose the language. Or those writing go will see their code transpiled to Rust before flashing.
The case for Go is broadening the audience, inclusivity for it’s own sake. Grow the community and everyone benefits.
This doesn’t address any of my questions and as someone who has experience writing go I don’t agree with the notion that go is democratizing anything for anyone. It’s an acceptable language but without a GC? No thanks.
C has many undefined behaviour conditions. It has become a rat’s nest of corner cases in the most recent standard.
I’m pretty sure one can write in TinyGo so that memory allocation is well defined and easy enough to reason about. One could probably also come up with tools that would help ensure compliance.
Although small C programs can be fun to write (I’ve been writing C for over 40 years), I find Go far more fun to work with.
TinyGo has GC (https://aykevl.nl/2020/09/gc-tinygo/), and also support for goroutines and channels so no RTOS needed.
So does the gc work on Arduino or not? I understand why it wouldn’t for WASM.
Without GC? Or just not-fast GC:
Not-fast GC. And when your memory is severely constrained, you may not want GC at all due to risk of fragmented memory (gc in tinygo is pure mark-sweep, not a copying collector).
For most applications, the GC in tinygo is fine.
Tinygo has GC.
I thought I’d take a tiny go at a comment on tinygo, to go with the article.
How did it go?
that’s pretty pointless
I enjoy writing network code using golang and everytime I hear about tinygo I check and still no networking support for Espressif chips. Maybe someday.
The article here isn’t particularly clear, but wifi is supported on many chips. I use the PicoW and Pico2W all the time and the wifi works very, very well.
To be honest I feel like for microcontrollers specifically that Zig/Microzig will eventually be a better fit for people not wanting to use C/Rust. The demand for smaller go binaries is massive and people already comfortable with go and just needing to do a quick project will gravitate to tinygo so I don’t see it losing google’s backing.