构建基于Go语言的高性能命令行AI对话客户端:从环境部署到核心实现

· 后端开发教程

现在人工智能变得越来越快,很多人开始把大语言模型的能力加进自己本地的工具里,这样能帮开发者更快地完成工作。命令行程序因为体积小、反应快,还能和其他脚本配合使用,一直是工程师每天离不开的好帮手。

这篇文章会从头开始,教你用 Go 语言做一个又快又省资源的终端 AI 聊天工具,它能和像 OpenAI、Ollama 这样的主流大模型接口通信,一边打字一边出结果,用起来顺手,以后也容易加新功能。

为什么选 Go 语言?

Go 写代码简单,处理多个任务也很轻松(靠的是 goroutine 和 channel),编译速度很快,而且可以直接生成一个单独的可执行文件,特别适合做命令行工具。它不需要额外装虚拟机或者解释器,编出来的程序在目标电脑上点一下就能跑,分发和安装都特别方便。另外,Go 自带的库已经支持网络请求、JSON 数据处理、命令行参数读取这些常见需求,写起来不用东拼西凑,省了很多麻烦。

开发环境配置

你要确认电脑上已经装了 Go(建议用 1.20 或更新的版本),可以用下面这行命令看看:

go version

然后新建一个文件夹作为项目目录,并初始化 Go 模块:

mkdir ai-cli && cd ai-cli
go mod init ai-cli

我们会用 urfave/cli/v2 来处理用户输入的命令和选项,这个库能让命令结构更清晰,参数解析也更简单:

go get github.com/urfave/cli/v2

至于发网络请求和处理 JSON,Go 自己就带了这些功能(比如 net/httpencoding/json),不用再额外下载别的包。

整体架构规划

这个工具主要由几个部分组成:第一是命令入口,负责读用户敲的命令和参数;第二是配置加载,用来读 API 密钥、模型名称、服务地址这些设置;第三是 API 适配层,把不同平台的请求格式统一起来(比如让 Ollama 也能用 OpenAI 那套格式);第四是流式响应处理,支持服务器一边算一边发字,这样回复看起来就像真人打字一样;最后是终端显示部分,要把 AI 的回答清楚地展示出来,还可以加颜色、控制光标位置,让界面更友好。

配置文件设计

我们用 YAML 格式来存配置,默认放在用户主目录下的 ~/.ai-cli/config.yaml 文件里,内容大概长这样:

api_key: "your-api-key"
model: "gpt-4o"
base_url: "https://api.openai.com/v1"
stream: true

读这个文件要用 gopkg.in/yaml.v3 这个包:

go get gopkg.in/yaml.v3

写加载逻辑的时候,先试着找用户目录里的配置文件;如果找不到,就提示用户去创建一个,而不是直接报错。

封装 API 调用逻辑

以 OpenAI 兼容的接口为例,先定义好要发的数据结构:

type ChatCompletionRequest struct {
    Model    string    `json:"model"`
    Messages []Message `json:"messages"`
    Stream   bool      `json:"stream"`
}

type Message struct {
    Role    string `json:"role"`
    Content string `json:"content"`
}

接着用 http.Client 发一个 POST 请求。关键是怎么处理那种“边算边回”的情况——当 stream 设成 true 时,服务器会用 text/event-stream 的方式不断推送新词。我们需要一行一行读服务器返回的内容,只处理以 data: 开头的那些行:

resp, err := client.Do(req)
if err != nil { /* 处理错误 */ }

defer resp.Body.Close()
scanner := bufio.NewScanner(resp.Body)

for scanner.Scan() {
    line := scanner.Text()
    if strings.HasPrefix(line, "data: ") {
        payload := strings.TrimPrefix(line, "data: ")
        if payload == "[DONE]" {
            break
        }
        // 把这一段 JSON 解开,拿到新增的文字
    }
}

优化终端交互体验

为了让回答看起来像有人在打字,不能等整段话都来了才显示,而是一收到新字就立刻打印出来。Go 的 fmt.Print 在大多数终端里都能正常工作,但要注意别不小心多输出了换行符,影响排版。

还可以给 AI 的回答加上颜色(比如绿色),这样一眼就能分清哪句是用户说的、哪句是 AI 回的,看着更舒服。实现方法可以是直接用 ANSI 转义字符,也可以引入像 github.com/muesli/termenv 这样的小工具。

多轮对话也是基本需求。我们可以在内存里记住之前的聊天记录,每次发请求时都带上这些上下文。再加一个 --clear 命令,让用户随时清空历史,重新开始一段新对话。

构建与分发

写完代码后,用下面的命令就能生成不同操作系统的可执行文件:

# Linux
GOOS=linux GOARCH=amd64 go build -o ai-cli-linux .

# macOS
GOOS=darwin GOARCH=amd64 go build -o ai-cli-mac .

# Windows
GOOS=windows GOARCH=amd64 go build -o ai-cli.exe .

Go 编出来的程序是“自包含”的,不需要用户再装运行环境,下载下来双击(或在终端运行)就能用。

面向未来的扩展

以后如果想支持更多后端,比如 Ollama、Claude,或者你自己搭的本地模型,改起来也不难。只要定一个通用的 Backend 接口,每个平台写自己的实现就行。用户只需要在配置文件里把 backend 改成 ollama,就能自动切换引擎。

还可以加一些实用的小功能,比如设个短命令 aic 代替全名、让 Shell 自动补全命令、把聊天记录存到 ~/.ai-cli/history 文件里,下次打开还能接着聊,用起来更顺手。

结语

通过 Go 语言,我们做出了一个轻巧、快速、容易维护的命令行 AI 聊天工具。它不光能用来日常对话,还能嵌入到自动化流程里,比如跑 CI/CD、分析日志、辅助写代码等等。更重要的是,这展示了怎么把 AI 真正变成开发者手边的一个实用小工具,而不是一个遥远的黑盒子。