Go выходит за пределы серверов: теперь язык добрался до железа
Go долго жил в довольно понятной нише: серверы, API, микросервисы, Kubernetes, сетевые инструменты. Если разработчику нужно было писать код для железа, выбор обычно выглядел совсем иначе - C, C++, а теперь ещё и Rust.
Но эта граница постепенно сдвигается.
TinyGo 0.42 получил новые возможности для embedded-разработки, а сам проект всё глубже уходит в мир микроконтроллеров, беспроводных устройств и систем, которые работают ещё до запуска операционной системы. В новой версии появились recoverable panic, поддержка Go 1.27 и LLVM 22, UEFI target, а вокруг проекта развивается готовый Starter Kit с ESP32-C3.
Для проекта, который когда-то было легко воспринимать как способ «запустить немного Go на маленькой плате», это уже довольно серьёзное развитие.
TinyGo постепенно разбирается с теми ограничениями, из-за которых Go долго оставался чужим для embedded-разработки: памятью, runtime, поддержкой конкретного железа и поведением программы при ошибках.
Почему обычный Go здесь не подходит
Микроконтроллер - совсем не сервер.
На сервере можно рассчитывать на гигабайты оперативной памяти, полноценную операционную систему и достаточно мощный процессор. У микроконтроллера всё гораздо скромнее: ограниченная память, небольшой объём флеш-хранилища, конкретный набор периферии и гораздо меньше свободы для разработчика.
Сам Go изначально создавался под другие условия. Его runtime рассчитан на среду, где ресурсов достаточно.
TinyGo решает проблему на уровне компиляции: Go-код превращается в более компактные программы, которые можно запускать в том числе на микроконтроллерах.
Но одного уменьшения бинарника недостаточно. Если привычные конструкции языка начинают вести себя иначе, разработчику приходится постоянно держать в голове особенности платформы.
И вот здесь изменения последних версий TinyGo становятся особенно заметны.
Panic теперь можно перехватывать
Одна из заметных новинок TinyGo 0.42 - recoverable runtime panics.
В обычном Go panic останавливает выполнение текущей горутины, а recover() позволяет перехватить панику внутри defer. Для разработчиков Go это давно знакомый механизм.
В TinyGo его возможности были гораздо более ограниченными.
Теперь некоторые runtime-ошибки можно обрабатывать привычным способом. Например, речь идёт о разыменовании nil-указателя, выходе за границы slice или map и делении на ноль. Для этого можно использовать обычные defer и recover.
При этом TinyGo не пытается сделать восстанавливаемой любую ошибку. Нехватка памяти, например, остаётся фатальной.
Для embedded это важное различие. Если устройство должно работать автономно и долго не иметь контакта с разработчиком, возможность обработать часть runtime-сбоев уже имеет вполне практический смысл.
Go может работать ещё до запуска операционной системы
В TinyGo 0.42 появился новый UEFI target.
UEFI работает до загрузки операционной системы, поэтому приложение в такой среде находится практически у самого основания программного стека.
Для Go это довольно необычная территория.
Получается любопытная ситуация: язык, который чаще всего связывают с HTTP-серверами, backend и инфраструктурой, теперь можно использовать для приложения, запускающегося ещё до загрузки ОС.
Это не значит, что Go внезапно начал конкурировать с C или Rust во всей firmware-разработке. До такого вывода пока очень далеко.
Но сам UEFI target хорошо показывает направление TinyGo. Проект постепенно спускается туда, где Go раньше практически не использовали.
Микроконтроллер превращается в сетевое устройство
Ещё один важный кусок этой истории появился в TinyGo 0.41.
Проект расширил работу с беспроводными возможностями ESP32-C3 и ESP32-S3. Появилась нативная поддержка Wi-Fi и Bluetooth через espradio, а утилита espflasher упростила загрузку программ на устройства.
И здесь меняется само представление о том, что именно мы делаем на микроконтроллере.
Плата с Wi-Fi - это уже не просто датчик, светодиод или кнопка. Она может обмениваться данными по сети, взаимодействовать с периферией и выполнять собственную логику на edge-устройстве.
Для Go это особенно интересно: разработчик получает знакомый язык там, где раньше почти автоматически приходилось переходить на другой стек.
Но TinyGo развивается не только вокруг железа
Есть ещё одно направление - WebAssembly.
TinyGo умеет компилировать Go в компактные .wasm-бинарники и WASI-приложения. Это позволяет использовать Go в средах, где WebAssembly выступает самостоятельным runtime, в том числе в edge-сценариях.
Причём возможности здесь уже довольно серьёзные. TinyGo поддерживает работу с горутинами в WebAssembly-окружениях, а Binaryen Asyncify позволяет использовать стандартные Go goroutines при GOMAXPROCS=1.
Показательный пример - typescript-go, новый компилятор TypeScript от Microsoft, написанный на Go. Команде TinyGo удалось собрать его целиком в WebAssembly.
Это уже далеко от классического сценария «скомпилировали небольшую программу для платы».
Получается, TinyGo одновременно двигается в нескольких направлениях: микроконтроллеры, WebAssembly и edge-среды.
У проекта появилось и своё железо
Вместе с программными изменениями развивается TinyGo Starter Kit, созданный совместно с Seeed Studio.
В комплект входит XIAO ESP32-C3, Grove Base и 11 модульных компонентов. Среди них датчики температуры, света и касания, OLED-дисплей, зуммер и RGB-компоненты.
На первый взгляд это просто набор для обучения.
Но для TinyGo он решает вполне практическую проблему. Embedded-разработка часто начинается с поиска подходящей платы, датчиков, способов подключения и инструментов прошивки. Даже простая демонстрация может потребовать больше подготовки, чем написание самого кода.
Готовый комплект сокращает этот путь. Можно взять плату, подключить модуль и сразу экспериментировать с Go.
Для языка, который долго воспринимался как серверный, это довольно показательный способ зайти в новую область.
Но C и Rust никуда не делись
Здесь легко переоценить происходящее.
Embedded-разработка требует гораздо большего контроля, чем обычный backend. Имеют значение конкретный процессор, объём памяти, периферия, драйверы, ограничения runtime и поведение программы при сбоях.
В некоторых проектах критичны предсказуемость выполнения и возможность контролировать практически каждый уровень системы.
Поэтому появление recover, UEFI или Wi-Fi-поддержки ещё не превращает TinyGo в универсальную замену C или Rust.
Но аргумент против Go постепенно меняется.
Раньше его можно было сформулировать довольно просто: язык удобный, но для микроконтроллеров слишком много ограничений.
Теперь часть этих ограничений последовательно снимается.
Go всё дальше уходит от образа только серверного языка
Именно это в истории TinyGo кажется мне самым интересным.
Проект уже не ограничивается демонстрацией того, что Go вообще можно запустить на микроконтроллере. Разработчики добавляют нормальную обработку runtime-паник, новые платформы, Wi-Fi и Bluetooth, инструменты прошивки, WebAssembly и готовое железо.
При этом направления начинают пересекаться.
Go уже давно чувствует себя уверенно на сервере. Через WebAssembly он выходит в другие runtime и edge-среды. TinyGo переносит его на микроконтроллеры. UEFI позволяет использовать Go ещё до загрузки операционной системы.
До универсального языка «для всего» ему по-прежнему далеко.
Но образ Go как языка исключительно для backend и инфраструктуры постепенно устаревает. TinyGo 0.42 - ещё один довольно наглядный пример того, насколько далеко этот сдвиг уже зашёл.
Комментарии
Чтобы оставить комментарий, войдите в аккаунт.