Интерфейс терминала: BubbleTea (Go) vs Ratatui (Rust)
Быстрый обзор фреймворков TUI в стиле Elm (Go) и immediate-mode (Rust)
Два мощных варианта для создания терминальных пользовательских интерфейсов сегодня — это BubbleTea (Go) и Ratatui (Rust). Один предлагает вам opinionated-фреймворк в стиле Elm; другой — гибкую библиотеку immediate-mode.
Эта статья подводит итог тому, что такое каждый из них, показывает минимальные примеры для обоих и предлагает, когда выбирать тот или иной. И да, также дает несколько полезных ссылок.

Crush UI (скриншот выше) реализован с использованием фреймворка BubbleTea.
Что такое BubbleTea?
BubbleTea — это фреймворк для Go, предназначенный для TUIs на основе The Elm Architecture. Вы описываете свое приложение с помощью модели (состояния) и трех компонентов: Init (начальная команда), Update (обработка сообщений, возврат новой модели и опциональной команды), и View (рендеринг интерфейса в виде строки). Фреймворк запускает цикл событий, преобразует нажатия клавиш и I/O в сообщения и перерисовывает интерфейс при изменении модели. Итак: что такое BubbleTea? Короче говоря, это веселый, состоятельный способ создания терминальных приложений на Go, с единственным источником истины и предсказуемыми обновлениями.
BubbleTea готова к производству (v1.x), имеет десятки тысяч звезд на GitHub и тысячи известных импортеров, и работает встроенной, полноэкранной или смешанной. Обычно его сочетают с Bubbles для компонентов (входы, viewport, спиннеры) и Lip Gloss для стилизации. Если вы создаете Go TUI, хороший первый шаг — следовать распространенной структуре Go-проектов, чтобы ваши cmd/ и пакеты оставались понятными по мере роста приложения.
Минимальная программа на BubbleTea выглядит так: модель, Init, Update (обработка сообщений клавиш) и View, возвращающая строку. Остальное делает рантайм.
package main
import (
"fmt"
"os"
tea "github.com/charmbracelet/bubbletea"
)
type model struct {
choices []string
cursor int
selected map[int]struct{}
}
func (m model) Init() tea.Cmd { return nil }
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q":
return m, tea.Quit
case "up", "k":
if m.cursor > 0 { m.cursor-- }
case "down", "j":
if m.cursor < len(m.choices)-1 { m.cursor++ }
case "enter", " ":
if _, ok := m.selected[m.cursor]; ok {
delete(m.selected, m.cursor)
} else {
m.selected[m.cursor] = struct{}{}
}
}
}
return m, nil
}
func (m model) View() string {
s := "Что нам купить?\n\n"
for i, choice := range m.choices {
cursor := " "
if m.cursor == i { cursor = ">" }
checked := " "
if _, ok := m.selected[i]; ok { checked = "x" }
s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice)
}
return s + "\nНажмите q для выхода.\n"
}
func main() {
if _, err := tea.NewProgram(model{
choices: []string{"Купить морковь", "Купить сельдерей", "Купить кольраби"},
selected: make(map[int]struct{}),
}).Run(); err != nil {
fmt.Printf("ошибка: %v", err)
os.Exit(1)
}
}
Известные приложения, созданные с использованием BubbleTea, включают Crush (TUI-основанный AI-кодинговый агент Charm), Glow, Huh и многие инструменты из экосистемы самых популярных Go-проектов. Для более сложных Go-приложений вы можете добавить внедрение зависимостей и надежные модульные тесты; те же идеи применимы к моделям и командам BubbleTea.
Что такое Ratatui?
Ratatui — это библиотека для Rust, предназначенная для TUIs, использующая рендеринг в immediate-mode: каждый кадр вы описываете весь интерфейс (виджеты и макет), и Ratatui его рисует. Что такое Ratatui? Это легковесный, неопределяющий инструментарий — он не навязывает модель в стиле Elm или определенную структуру приложения. Вы сохраняете свое состояние, запускаете свой цикл событий (обычно с crossterm, termion, или termwiz), и вызываете terminal.draw(|f| { ... }) для рендеринга. Таким образом, разница между стилем Elm и immediate mode заключается именно в этом: в стиле Elm фреймворк владеет циклом, и вы реагируете через Update/View; в immediate mode вы владеете циклом и перерисовываете весь интерфейс из текущего состояния каждый кадр.
Ratatui используется в 2,100+ кратах и доверяется компаниями, такими как Netflix (например, bpftop), OpenAI, AWS (например, amazon-q-developer-cli), и Vercel. Версия 0.30.x является текущей, с сильной документацией и опциональными бэкендами. Это хороший выбор, когда вы хотите полный контроль над вводом и рендерингом, или когда вы уже в экосистеме Rust.
Минимальное приложение Ratatui: вы инициализируете терминал, запускаете цикл, который рисует и затем считывает события, и восстанавливаете терминал при выходе.
use crossterm::event::{self, Event, KeyCode};
use ratatui::{prelude::*, widgets::Paragraph};
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut terminal = ratatui::init();
loop {
terminal.draw(|frame| {
let area = frame.area();
frame.render_widget(
Paragraph::new("Привет, Ratatui! Нажмите q для выхода.").alignment(Alignment::Center),
area,
);
})?;
if event::poll(Duration::from_millis(250))? {
if let Event::Key(key) = event::read()? {
if key.code == KeyCode::Char('q') {
break;
}
}
}
}
ratatui::restore();
Ok(())
}
Итак: когда мне выбирать BubbleTea или Ratatui? Выбирайте BubbleTea, когда вы хотите самый быстрый путь к отполированному TUI на Go, с одной моделью и четким Update/View, и когда ваша команда или экосистема — это Go (например, вы уже используете Go ORMs или Ollama в Go). Выбирайте Ratatui, когда вам нужен максимальный контроль, вы работаете в Rust, или создаете TUIs с высокими требованиями к производительности или ограниченными ресурсами; его дизайн immediate-mode и опциональные бэкенды обеспечивают эту гибкость.
Сводка
| Аспект | BubbleTea (Go) | Ratatui (Rust) |
|---|---|---|
| Стиль | Архитектура Elm (модель, Init/Update/View) | Immediate mode (вы владеете циклом, рисуете каждый кадр) |
| Экосистема | Bubbles, Lip Gloss, 10k+ приложений, Crush | 2,100+ кратов, Netflix/OpenAI/AWS/Vercel |
| Лучше всего для | Быстрая итерация, команды Go, CLI | Контроль, производительность, кодовые базы Rust |
Оба варианта отличные; предпочтительный язык и сколько структуры мы хотим от фреймворка должны определять решение.
Полезные ссылки
- Топ 19 трендовых Go-проектов на GitHub - Январь 2026
- Топ 23 трендовых Rust-проектов на GitHub - Январь 2026
- Внедрение зависимостей в Go: паттерны и лучшие практики
- Go SDKs для Ollama - сравнение с примерами
- Сравнение Go ORMs для PostgreSQL: GORM vs Ent vs Bun vs sqlc
- Структура Go-проектов: практики и паттерны
- Go модульное тестирование: структура и лучшие практики