终端 UI:BubbleTea (Go) vs Ratatui (Rust)
It looks like only the source citation was provided. Could you please share the article text you’d like translated? Once I have the content, I’ll translate it into Simplified Chinese while preserving the formatting and code blocks.
BubbleTea (Go)
什么是 BubbleTea?
BubbleTea 是一个基于 The Elm Architecture 的 Go TUI 框架。你通过 模型(状态)以及以下三部分来描述你的应用:
| 部分 | 目的 |
|---|---|
| Init | 返回一个初始命令(或 nil)。 |
| Update | 处理传入的消息,返回新的模型和可选的命令。 |
| View | 将 UI 渲染为字符串。 |
框架负责运行事件循环,将按键和 I/O 转换为消息,并在模型变化时重新绘制 UI。简而言之,它是用 Go 构建终端应用的有趣、状态化方式,拥有唯一的真相来源和可预测的更新。
为什么选择 BubbleTea?
- 生产就绪(v1.x),拥有数万颗 GitHub 星。
- 支持行内、全屏或混合模式。
- 通常与 Bubbles(如输入框、视口、加载动画等组件)和 Lip Gloss(样式)一起使用。
- 自然契合典型的 Go 项目布局(
cmd/、包等)。
最小的 BubbleTea 程序
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 "
}
checked := " "
if _, ok := m.selected[i]; ok {
checked = "x"
}
s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice)
}
return s + "\nPress q to quit.\n"
}
func main() {
if _, err := tea.NewProgram(model{
choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"},
selected: make(map[int]struct{}),
}).Run(); err != nil {
fmt.Printf("error: %v", err)
os.Exit(1)
}
}
使用 BubbleTea 构建的知名应用
- Crush – Charm 的基于 TUI 的 AI 编码助手。
- Glow – Markdown 查看器。
- Huh – 交互式提示。
- 以及众多来自热门 Go 项目生态的工具。
对于更大的 Go 应用,你可以加入依赖注入、完善的单元测试以及其他符合 Go 习惯的模式;这些思路同样适用于 BubbleTea 的模型和命令。
Source: …
Ratatui(Rust)
Ratatui 是什么?
Ratatui 是一个用于 TUI(终端用户界面)的 Rust 库,采用 即时模式渲染:每一帧你都描述完整的 UI(部件和布局),Ratatui 负责绘制。
- 它轻量且不强加任何框架——不要求 Elm‑style 的模型或特定的应用结构。
- 你自行维护状态,运行自己的事件循环(通常使用 crossterm、termion 或 termwiz),并调用
terminal.draw(|f| { … })来渲染。
Elm‑style 与 Immediate‑mode
| 方法 | 循环的所有者 | UI 的描述方式 |
|---|---|---|
| Elm‑style(BubbleTea) | 框架 | Update → View(仅重绘改变的部分) |
| Immediate‑mode(Ratatui) | 你(应用) | 每帧根据当前状态重新构建整个 UI |
为什么选择 Ratatui?
- 被 2,100+ 个 crate 使用,且受到 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<()> {
// Initialise the terminal
let mut terminal = ratatui::init();
loop {
// Draw the UI each frame
terminal.draw(|frame| {
let area = frame.area();
frame.render_widget(
Paragraph::new("Hello, Ratatui! Press q to quit.")
.alignment(Alignment::Center),
area,
);
})?;
// Handle input (poll every 250 ms)
if event::poll(Duration::from_millis(250))? {
if let Event::Key(key) = event::read()? {
if key.code == KeyCode::Char('q') {
break;
}
}
}
}
// Restore the terminal state before exiting
ratatui::restore();
Ok(())
}
何时选择哪一个?
| 方面 | BubbleTea (Go) | Ratatui (Rust) |
|---|---|---|
| 架构 | Elm Architecture(模型 + Init/Update/View) | 即时模式(你掌控循环) |
| 生态系统 | Bubbles、Lip Gloss,10k+ 应用(例如 Crush) | 2,100+ crates,已被 Netflix、OpenAI、AWS、Vercel 使用 |
| 最佳适用 | 快速迭代、Go 团队、CLI | 完全控制、对性能敏感的 TUI、Rust 代码库 |
| 典型使用场景 | 想要在 Go 中最快速实现精致的 TUI | 需要最大控制或已经在使用 Rust |
结论: 两个框架都非常优秀。应根据首选语言以及你希望框架提供的结构化程度来决定使用哪一个。
进一步阅读与资源
- 2026 年 1 月 GitHub 上最热门的 19 个 Go 项目
- 2026 年 1 月 GitHub 上最热门的 23 个 Rust 项目
- Go 中的依赖注入:模式与最佳实践
上图的 Crush UI 是使用 BubbleTea 框架实现的。
Practices
- Go SDKs for Ollama – 示例比较
- Comparing Go ORMs for PostgreSQL: GORM vs Ent vs Bun vs sqlc → 比较 Go ORM(PostgreSQL):GORM vs Ent vs Bun vs sqlc
- Go Project Structure: Practices & Patterns → Go 项目结构:实践与模式
- Go Unit Testing: Structure & Best Practices → Go 单元测试:结构与最佳实践
- Bubble Tea – The Elm Architecture for Go TUIs → Bubble Tea – Go TUI 的 Elm 架构
- Ratatui – Introduction → Ratatui – 介绍
- Ratatui – Rendering (immediate mode) → Ratatui – 渲染(即时模式)
- Charm Crush – TUI coding agent → Charm Crush – TUI 编码代理
- Ratatui on crates.io → Ratatui 在 crates.io 上