Base64 是开发者日常高频使用的编码格式——JWT 解析、配置文件编码、API 数据传输都离不开它。本文展示如何用 OpenCode 从零构建一个功能齐全的命令行 Base64 编解码工具,支持标准/URL-safe Base64、文件输入、行宽控制和去填充模式。
encoding/base64、flag、os)确保已安装 Go(1.18+)和 OpenCode:
go version # go version go1.21.0 ... opencode --version
新建项目目录,在 OpenCode 中打开即可开始:
mkdir base64-cli && cd base64-cli opencode .
我对 OpenCode 说:
> 帮我用 Go 写一个命令行 Base64 编解码工具,支持 -d 参数切换解码模式,默认从标准输入读取,结果输出到标准输出。只使用标准库。
OpenCode 生成:
// main.go
package main
import (
"encoding/base64"
"flag"
"fmt"
"io"
"os"
)
func main() {
decode := flag.Bool("d", false, "decode mode")
flag.Parse()
input, _ := io.ReadAll(os.Stdin)
if *decode {
result, err := base64.StdEncoding.DecodeString(string(input))
if err != nil {
fmt.Fprintf(os.Stderr, "decode error: %v\n", err)
os.Exit(1)
}
os.Stdout.Write(result)
} else {
output := base64.StdEncoding.EncodeToString(input)
fmt.Print(output)
}
}
测试一下:
echo "Hello OpenCode" | go run main.go # SGVsbG8gT3BlbkNvZGU= echo "SGVsbG8gT3BlbkNvZGU=" | go run main.go -d # Hello OpenCode
关键要点: 一句话描述需求,OpenCode 就能生成可直接运行的基础版本。不需要手动查 encoding/base64 的 API 文档。
我对 OpenCode 说:
> 加一个 -u 参数支持 URL-safe Base64(用 - 和 _ 替代 + 和 /),编解码都要支持。
OpenCode 修改后的核心逻辑:
urlsafe := flag.Bool("u", false, "use URL-safe Base64")
// 编解码时根据 -u 选择编码集
enc := base64.StdEncoding
if *urlsafe {
enc = base64.URLEncoding
}
测试验证:
echo "a>b?c" | go run main.go -u # YT5iP2M= echo "YT5iP2M=" | go run main.go -d -u # a>b?c
关键要点: 功能叠加只需追加自然语言描述,OpenCode 理解上下文后精准定位要修改的位置,不会重写整个文件。
我对 OpenCode 说:
> 支持从文件读取输入(go run main.go file.txt)。编码输出时默认每 76 个字符换行,加 -w 参数关闭换行。
OpenCode 生成的关键改动:
var input []byte
if flag.NArg() > 0 {
input, _ = os.ReadFile(flag.Arg(0))
} else {
input, _ = io.ReadAll(os.Stdin)
}
// 行宽控制
noWrap := flag.Bool("w", false, "disable line wrapping")
if !*noWrap {
for i := 0; i < len(output); i += 76 {
end := i + 76
if end > len(output) {
end = len(output)
}
fmt.Println(output[i:end])
}
} else {
fmt.Print(output)
}
测试文件输入:
go run main.go go.mod # bW9kdWxlIGJhc2U2NC1jbGkKCmdvIDEuMjE=
关键要点: OpenCode 自动处理了管道输入与文件输入的优先级——有文件名就优先读文件,否则从 stdin 读取。这种细节不需要手动指定。
我对 OpenCode 说:
> 再加一个 -p 参数,去掉 Base64 的 = 填充。需要和 -u 参数组合使用也正确。
OpenCode 修改:
noPad := flag.Bool("p", false, "omit padding")
// 四种编码组合
switch {
case *urlsafe && *noPad:
enc = base64.RawURLEncoding
case *urlsafe:
enc = base64.URLEncoding
case *noPad:
enc = base64.RawStdEncoding
default:
enc = base64.StdEncoding
}
测试组合参数:
echo "hello" | go run main.go -u -p # aGVsbG8 echo "aGVsbG8" | go run main.go -d -u -p # hello
关键要点: OpenCode 正确理解了 urlsafe + noPad 需要 RawURLEncoding 而非简单的逻辑叠加,说明它能理解 API 之间的语义关系。
package main
import (
"encoding/base64"
"flag"
"fmt"
"io"
"os"
)
func main() {
decode := flag.Bool("d", false, "decode mode")
urlsafe := flag.Bool("u", false, "use URL-safe Base64")
noWrap := flag.Bool("w", false, "disable line wrapping (76 chars)")
noPad := flag.Bool("p", false, "omit padding characters")
help := flag.Bool("h", false, "show help")
flag.Parse()
if *help {
fmt.Println("base64-cli - Base64 encode/decode utility")
fmt.Println("Usage: base64-cli [flags] [file]")
fmt.Println("Flags:")
flag.PrintDefaults()
fmt.Println("Examples:")
fmt.Println(" echo 'hello' | base64-cli")
fmt.Println(" echo 'aGVsbG8=' | base64-cli -d")
fmt.Println(" echo 'a>b' | base64-cli -u")
fmt.Println(" base64-cli -u -p -w file.txt")
return
}
var input []byte
var err error
if flag.NArg() > 0 {
input, err = os.ReadFile(flag.Arg(0))
} else {
input, err = io.ReadAll(os.Stdin)
}
if err != nil {
fmt.Fprintf(os.Stderr, "read error: %v\n", err)
os.Exit(1)
}
if *decode {
var enc *base64.Encoding
switch {
case *urlsafe:
enc = base64.URLEncoding
case *noPad:
enc = base64.RawStdEncoding
default:
enc = base64.StdEncoding
}
result, err := enc.DecodeString(string(input))
if err != nil {
fmt.Fprintf(os.Stderr, "decode error: %v\n", err)
os.Exit(1)
}
os.Stdout.Write(result)
} else {
var enc *base64.Encoding
switch {
case *urlsafe && *noPad:
enc = base64.RawURLEncoding
case *urlsafe:
enc = base64.URLEncoding
case *noPad:
enc = base64.RawStdEncoding
default:
enc = base64.StdEncoding
}
output := enc.EncodeToString(input)
if *noWrap {
fmt.Print(output)
} else {
for i := 0; i < len(output); i += 76 {
end := i + 76
if end > len(output) {
end = len(output)
}
fmt.Println(output[i:end])
}
}
}
}
从零到功能完备的命令行工具,共用 4 轮对话、实际耗时约 5 分钟。按传统方式开发,需要用 go doc encoding/base64 查阅 API、手写 flag 解析逻辑、处理各种边界条件,至少需要 20-30 分钟。
OpenCode 的核心价值不在"生成代码",而在于"消除上下文切换"——不需要在编辑器、文档、搜索引擎之间往返。描述需求 → 得到可运行代码 → 验证 → 继续迭代,所有步骤都在终端内完成,思考不中断。
这次实践用到的 OpenCode 技巧:
精确描述输入输出——"从标准输入读取,结果输出到标准输出"让 OpenCode 直接生成管道友好的代码
逐层叠加功能——不要一次性描述所有需求,先跑通基础版再迭代,每轮验证更快
信任上下文理解——OpenCode 修改代码时不重写整个文件,只改相关部分,这和 ChatGPT 的"每次重来"体验完全不同