Base64 编码是开发中高频操作——无论是处理文件上传、配置 JWT Token,还是查看二进制数据,都离不开它。虽然网上有不少在线工具,但频繁切换浏览器很打断思路。今天我们用 OpenCode 写一个命令行 Base64 编解码器,编码/解码一句话搞定。
最终效果:
# 编码字符串 $ echo "Hello OpenCode" | base64tool SGVsbG8gT3BlbkNvZGU= # 解码 $ echo "SGVsbG8gT3BlbkNvZGU=" | base64tool -d Hello OpenCode # URL 安全编码 $ echo "hello+world/one" | base64tool -u aGVsbG8rd29ybGQvb25l # 从文件编码并控制行宽 $ base64tool -w 64 image.png > image_b64.txt
打开终端,进入工作目录,对 OpenCode 说:
> 我对 OpenCode 说:
>
> 用 Go 标准库帮我写一个 Base64 编解码命令行工具。支持 -d 解码模式和 -e 编码模式(默认编码),从标准输入读取数据,结果输出到标准输出。项目名叫 base64tool,保存到 base64tool/main.go。
OpenCode 秒级生成了以下代码:
package main
import (
"encoding/base64"
"flag"
"fmt"
"io"
"os"
)
func main() {
decode := flag.Bool("d", false, "解码模式")
encode := flag.Bool("e", false, "编码模式")
flag.Parse()
if !*decode && !*encode {
*encode = true
}
input, err := io.ReadAll(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "读取输入失败: %v\n", err)
os.Exit(1)
}
if *decode {
decoded, err := base64.StdEncoding.DecodeString(string(input))
if err != nil {
fmt.Fprintf(os.Stderr, "Base64 解码失败: %v\n", err)
os.Exit(1)
}
os.Stdout.Write(decoded)
} else {
encoded := base64.StdEncoding.EncodeToString(input)
fmt.Print(encoded)
}
}
> 关键要点:你不需要告诉 OpenCode 每个函数名或每行代码怎么写——只要描述清楚"做什么"和"怎么用",OpenCode 自动选用合适标准库并实现功能。
验证一下:
$ go run base64tool/main.go <<< "hello" aGVsbG8=
编码正确,第一步完成。
基础功能跑通后,加两个更实用的特性:
> 我对 OpenCode 说:
>
> 给这个工具加两个功能:1) 添加 -u 参数,使用 URL 安全的 Base64 编解码(base64.URLEncoding);2) 支持从文件读取输入,当命令行有额外参数时当做文件路径打开。更新 main.go。
OpenCode 精准理解需求,下面是新增 -u 参数和文件读取逻辑后的代码:
package main
import (
"encoding/base64"
"flag"
"fmt"
"io"
"os"
)
func main() {
decode := flag.Bool("d", false, "解码模式")
urlSafe := flag.Bool("u", false, "使用 URL 安全的 Base64 编码")
flag.Parse()
encoding := base64.StdEncoding
if *urlSafe {
encoding = base64.URLEncoding
}
var input io.Reader = os.Stdin
if args := flag.Args(); len(args) > 0 {
f, err := os.Open(args[0])
if err != nil {
fmt.Fprintf(os.Stderr, "无法打开文件 %s: %v\n", args[0], err)
os.Exit(1)
}
defer f.Close()
input = f
}
data, err := io.ReadAll(input)
if err != nil {
fmt.Fprintf(os.Stderr, "读取输入失败: %v\n", err)
os.Exit(1)
}
if *decode {
decoded, err := encoding.DecodeString(string(data))
if err != nil {
fmt.Fprintf(os.Stderr, "Base64 解码失败: %v\n", err)
os.Exit(1)
}
os.Stdout.Write(decoded)
} else {
result := encoding.EncodeToString(data)
fmt.Print(result)
}
}
> 关键要点:OpenCode 做到了"增量修改"——只改动相关部分,逻辑结构保持不变。你用自然语言说"加个什么",OpenCode 就能准确定位需要修改的位置。
测试时发现:从管道输入的内容带换行符,可能导致解码失败。我对 OpenCode 说:
> 我对 OpenCode 说:
>
> 解码前先用 strings.TrimSpace 去掉输入中的空白字符,因为管道或文件输入可能带换行符。另外编码输出时加 -w 参数控制每行输出宽度,默认 76 字符(符合 RFC 4648 建议)。
OpenCode 引入 strings 包并在解码前加了 TrimSpace,同时实现了分行输出逻辑:
package main
import (
"encoding/base64"
"flag"
"fmt"
"io"
"os"
"strings"
)
func main() {
decode := flag.Bool("d", false, "解码模式")
urlSafe := flag.Bool("u", false, "使用 URL 安全的 Base64 编码")
wrap := flag.Int("w", 76, "编码输出每行宽度(0 表示不换行)")
flag.Parse()
encoding := base64.StdEncoding
if *urlSafe {
encoding = base64.URLEncoding
}
var input io.Reader = os.Stdin
if args := flag.Args(); len(args) > 0 {
f, err := os.Open(args[0])
if err != nil {
fmt.Fprintf(os.Stderr, "无法打开文件 %s: %v\n", args[0], err)
os.Exit(1)
}
defer f.Close()
input = f
}
data, err := io.ReadAll(input)
if err != nil {
fmt.Fprintf(os.Stderr, "读取输入失败: %v\n", err)
os.Exit(1)
}
if *decode {
trimmed := strings.TrimSpace(string(data))
decoded, err := encoding.DecodeString(trimmed)
if err != nil {
fmt.Fprintf(os.Stderr, "Base64 解码失败: %v\n", err)
os.Exit(1)
}
os.Stdout.Write(decoded)
} else {
result := encoding.EncodeToString(data)
if *wrap > 0 {
for i := 0; i < len(result); i += *wrap {
end := i + *wrap
if end > len(result) {
end = len(result)
}
fmt.Println(result[i:end])
}
} else {
fmt.Print(result)
}
}
}
> 关键要点:OpenCode 不只是机械加代码,它理解了为什么要 trim——因为管道输入带换行符是高频踩坑点。同时分行逻辑写得高效简洁,一个循环搞定。
代码写完了,让 OpenCode 自己测试:
> 我对 OpenCode 说:
>
> 帮我测试这个工具。分别测试:1) 编码和解码一段中文;2) 编码一张图片再解码还原;3) URL 安全编码;4) 分行输出效果。
OpenCode 逐一执行测试命令:
# 测试1:中文编解码 $ echo "你好,OpenCode!" | go run main.go | go run main.go -d 你好,OpenCode! # 测试2:图片编解码还原 $ go run main.go logo.png | go run main.go -d > logo_restored.png $ diff logo.png logo_restored.png && echo "文件一致" 文件一致 # 测试3 & 4:URL 安全编码 + 分行输出 $ echo "test data" | go run main.go -u -w 12 dGVzdCBkYXRh
> 关键要点:让 OpenCode 帮你测试——它能自己执行命令、分析输出、定位问题,比手动打命令快得多。
以下是最终版 main.go(约 85 行):
package main
import (
"encoding/base64"
"flag"
"fmt"
"io"
"os"
"strings"
)
func main() {
decode := flag.Bool("d", false, "解码模式")
urlSafe := flag.Bool("u", false, "使用 URL 安全的 Base64 编码")
wrap := flag.Int("w", 76, "编码输出每行宽度(0 表示不换行)")
flag.Parse()
encoding := base64.StdEncoding
if *urlSafe {
encoding = base64.URLEncoding
}
var input io.Reader = os.Stdin
if args := flag.Args(); len(args) > 0 {
f, err := os.Open(args[0])
if err != nil {
fmt.Fprintf(os.Stderr, "无法打开文件 %s: %v\n", args[0], err)
os.Exit(1)
}
defer f.Close()
input = f
}
data, err := io.ReadAll(input)
if err != nil {
fmt.Fprintf(os.Stderr, "读取输入失败: %v\n", err)
os.Exit(1)
}
if *decode {
trimmed := strings.TrimSpace(string(data))
decoded, err := encoding.DecodeString(trimmed)
if err != nil {
fmt.Fprintf(os.Stderr, "Base64 解码失败: %v\n", err)
os.Exit(1)
}
os.Stdout.Write(decoded)
} else {
result := encoding.EncodeToString(data)
if *wrap > 0 {
for i := 0; i < len(result); i += *wrap {
end := i + *wrap
if end > len(result) {
end = len(result)
}
fmt.Println(result[i:end])
}
} else {
fmt.Print(result)
}
}
}
# 编译安装 $ go build -o base64tool main.go # 常用命令 $ echo "Hello World" | base64tool # 编码 $ base64tool -d <<< "SGVsbG8=" # 解码 $ base64tool -u image.png > image.b64 # URL 安全编码文件 $ base64tool -w 64 <<< "long text..." # 每行 64 字符输出
整个开发过程不到 4 分钟,我做的事情只有三件:
描述需求——用一句话告诉 OpenCode 要做什么
迭代补充——发现不够用就加一句描述
测试验证——让 OpenCode 自己跑测试
回想传统开发流程:查标准库文档 → 写代码 → 调试 → 发现边界问题 → 再改 → 再测……而用 OpenCode,整个过程变成了"对话式开发"。你不用记 API 签名,不用纠结语法细节,专注描述"要什么"而不是"怎么写"。
一个 85 行的 Go 工具从零到可用的时间缩减到了分钟级,这就是 AI 编程助手的真正价值——不是替代你写代码,而是让你把精力放在更有创造性的决策上。