标签: Go

  • 🍵 一杯代码冲泡的珍珠奶茶:Go 语言 Bubble Tea 初探

    “在命令行里工作很酷,会让你感觉自己像黑客电影里的英雄。”

    此言不虚!但是,面对单调乏味的文字瀑布,或者令人望而生畏的命令行参数、美元符号前缀,以及各种莫名其妙的错误信息,我们也难免会感到力不从心。

    好在,终端世界里除了冰冷的命令行,还有生机勃勃的 TUI(终端用户界面)。TUI 就像一杯珍珠奶茶,在复古的外表下,蕴藏着现代化的体验。而在 Go 语言的世界里, Bubble Tea 库的出现,让制作 TUI 应用变得像泡一杯奶茶一样简单。

    🤔 为什么选择 Bubble Tea?

    想象一下,你是一位经验丰富的茶饮师,想要调制一杯独一无二的珍珠奶茶。这时,你会选择什么样的工具呢?

    Bubble Tea 就如同一个功能强大的工具箱,它提供了以下几个不可抗拒的优势:

    • 熟悉的 Elm 架构: 如果你已经习惯了 React、Vue 或 Elm 等前端框架,那么 Bubble Tea 的 Elm 架构对你来说一定不会陌生。这种架构就像奶茶的配方,清晰易懂,让你轻松上手。
    • 模块化的代码组织: Elm 架构不仅易于理解,而且非常适合构建模块化的 UI 代码。你可以从一个简单的应用开始,逐步添加功能,就像在奶茶中加入珍珠、椰果一样,让你的应用逐渐丰满起来。
    • 简洁易懂的 Go 语言: Go 语言以其简洁一致的语法著称,这使得阅读和理解他人的代码变得轻而易举。就像品尝一杯精心调制的奶茶,你能清晰地感受到每一种成分的味道。

    🚀 从 Hello World 开始

    俗话说,万事开头难。让我们从一个简单的 “Hello World” 应用开始,体验一下 Bubble Tea 的魅力吧!

    首先,创建一个名为 code-journal 的目录,并在终端中运行以下命令:

    go mod init
    go get github.com/charmbracelet/bubbletea

    然后,创建一个名为 app.go 的文件,并添加以下代码:

    package main
    
    import (
        tea "github.com/charmbracelet/bubbletea"
    )
    
    func main() {
        p := tea.NewProgram(
            newSimplePage(
                "This app is under construction",
            ),
        )
        if err := p.Start(); err != nil {
            panic(err)
        }
    }

    接下来,创建另一个名为 simple_page.go 的文件,其中包含我们的第一个 UI,一个只显示一些文本的简单页面:

    package main
    
    import (
    	"fmt"
    	"strings"
    
    	tea "github.com/charmbracelet/bubbletea"
    )
    
    // MODEL DATA
    type simplePage struct {
    	text string
    }
    
    func newSimplePage(text string) simplePage {
    	return simplePage{
    		text: text,
    	}
    }
    
    func (s simplePage) Init() tea.Cmd {
    	return nil
    }
    
    // VIEW
    func (s simplePage) View() string {
    	textLen := len(s.text)
    	topAndBottomBar := strings.Repeat("*", textLen+4)
    	return fmt.Sprintf("%s\n* %s *\n%s\n\nPress Ctrl+C to exit", topAndBottomBar, s.text, topAndBottomBar)
    }
    
    // UPDATE
    func (s simplePage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
    	switch msg.(type) {
    	case tea.KeyMsg:
    		switch msg.(tea.KeyMsg).String() {
    		case "ctrl+c":
    			return s, tea.Quit
    		}
    	}
    	return s, nil
    }

    在终端中运行以下命令,编译并运行我们的应用:

    go build ./code-journal

    你将会看到如下输出:

    ************************
    * This app is under construction *
    ************************
    
    Press Ctrl+C to exit

    恭喜你!你已经成功运行了你的第一个 Bubble Tea 应用。

    🔬 剖析代码

    现在,让我们像品尝奶茶一样,细细品味一下这段代码。

    🧋 Model:Bubble Tea 的核心

    main 函数通过创建一个新的 simplePage 模型来启动程序。

    p := tea.NewProgram(
        newSimplePage(
            "This app is under construction",
        ),
    )

    我们调用了 tea.NewProgram 函数,它的函数签名如下:

    func NewProgram(initialModel Model) *Program

    然后调用该程序的 Start 方法来启动我们的应用程序。但是 initialModel 是什么呢?

    ModelBubble Tea 的核心接口,它定义了三个方法:

    type Model interface {
        Init() Cmd
        Update(msg Msg) (Model, Cmd)
        View() string
    }
    • Init() 方法在应用程序启动时被调用,并返回一个 tea.CmdCmd 可以理解为 “幕后发生的事情”,例如加载数据或计时器。在本教程中,我们没有任何后台操作,因此 Init 方法只返回 nil
    func (s simplePage) Init() tea.Cmd {
        return nil
    }
    • View() 方法是 Bubble Tea 中一个很酷的抽象,它将整个 UI 的显示都表示为一个字符串!在 View 方法中,你需要构建并返回这个字符串。
    func (s simplePage) View() string {
        textLen := len(s.text)
        topAndBottomBar := strings.Repeat("*", textLen+4)
        return fmt.Sprintf("%s\n* %s *\n%s\n\nPress Ctrl+C to exit", topAndBottomBar, s.text, topAndBottomBar)
    }

    在上面的代码中,我们将 simplePage 的文本放在一个由星号组成的盒子里,并在底部显示一条消息 “Press Ctrl+C to exit”。

    • Update() 方法负责处理用户输入。
    func (s simplePage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
        switch msg.(type) {
        case tea.KeyMsg:
            switch msg.(tea.KeyMsg).String() {
            case "ctrl+c":
                return s, tea.Quit
            }
        }
        return s, nil
    }

    Update() 方法接收一个 tea.Msg 并返回一个新的 tea.Model,有时还会返回一个 tea.Cmd(例如,如果某个操作导致检索数据或计时器启动)。

    tea.Msg 的类型签名如下:

    type Msg interface{}

    所以它可以是任何类型,并携带你需要的数据。它有点像 JavaScript 中的浏览器事件;计时器事件不携带任何数据,点击事件会告诉你点击了什么,等等。

    我们正在处理的消息类型是 tea.KeyMsg,它表示键盘输入。我们检查用户是否按下了 Ctrl+C. 如果是,则返回 tea.Quit 命令,该命令属于 tea.Cmd 类型,并告诉 Bubble Tea 退出应用程序。

    对于任何其他类型的输入,我们不做任何处理,只是按原样返回模型。但是,如果我们正在执行 UI 导航等操作,则会更改模型上的一些字段,然后返回它,从而导致 UI 更新。

    ⏭️ 下一站:菜单组件

    在下一篇文章中,我们将学习如何创建一个菜单组件,并让我们的应用程序更加生动有趣!敬请期待!

人生梦想 - 关注前沿的计算机技术 acejoy.com 🐾 步子哥の博客 🐾 背多分论坛 🐾 知差(chai)网