OpenCode 实践课:4 分钟用 Go 写出一个命令行 JWT Token 解析器

项目介绍

JWT(JSON Web Token)是日常开发中随处可见的身份认证令牌。每次在调试接口时拿到一串 eyJhbG... 开头的密文,总要打开 jwt.io 粘贴解码,非常低效。

今天我们用 OpenCode 写一个命令行 JWT 解析器,终端里一行命令就能把 Token 的 Header 和 Payload 解码出来,支持从参数直接传入或从管道读取。

  • 语言:Go
  • 行数:约 100 行
  • 功能:解码 JWT 的三段结构(Header / Payload / Signature),Base64 解码 + JSON 美化输出

准备工作

  • Go 1.21+ 已安装
  • OpenCode 已安装(npm install -g @anthropic-ai/opencode 或参考 opencode.ai
  • 在项目目录下执行 opencode 启动交互会话

实践过程

第一步:初始化项目

我打开终端,进入空目录,对 OpenCode 说了第一句话:

> :帮我初始化一个 Go 项目,module 名叫 jwtdec,写一个 main.go,功能是命令行 JWT 解析工具。

OpenCode 立刻开始工作——它先执行 go mod init jwtdec,然后写出 main.go 骨架。它自动判断需要用 encoding/base64encoding/json 标准库来完成 Base64 解码和 JSON 美化,还贴心地加了 os.Argsos.Stdin 两种输入方式。

> 要点:OpenCode 会理解你的意图并补齐技术细节,你不需要记住标准库的包名。

第二步:实现 Base64 解码逻辑

JWT 的 Header 和 Payload 用的是 Base64URL 编码(无填充),直接拿标准库的 base64.StdEncoding 解会报错。我对 OpenCode 说:

> :JWT 用的是 Base64URL 编码且没有 padding,解码时需要补上 '=',帮我修正解码逻辑。

OpenCode 在解码函数里加了一段补全逻辑:

switch len(s) % 4 {
case 2:
    s += "=="
case 3:
    s += "="
}

然后改用 base64.URLEncoding 解码。完全正确。

> 要点:当你描述一个技术细节时(如编码格式),OpenCode 能准确找到对应的标准库方法,比翻文档快得多。

第三步:美化 JSON 输出

默认的 JSON 输出挤在一行,可读性很差。我继续提要求:

> :解码后的 JSON 用缩进美化输出,用 json.Indent

OpenCode 在解码函数返回前加入 json.Indent 调用,一行改动就搞定了。

> 要点:你不必写出完整代码,只需描述"我要什么效果",OpenCode 会找到最合适的 API。

第四步:添加错误处理和使用提示

最后我让它完善用户体验:

> :加上 usage 提示信息,当用户没传参数时显示用法;解码失败时打印友好错误信息而不是 panic。

OpenCode 迅速补全了完整的错误处理链,包括:

  • 无参数时的用法说明
  • Base64 解码失败时的具体错误提示
  • JSON 解析失败时的友好报错

到这里,整个工具就完成了。整个过程大约 4 分钟,我一直在用自然语言描述需求,一行代码都没亲手打。

完整代码

package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strings"
)

func main() {
	var token string

	if len(os.Args) > 1 {
		token = os.Args[1]
	} else {
		data, err := io.ReadAll(os.Stdin)
		if err != nil || len(data) == 0 {
			fmt.Println("usage: jwtdec <token>")
			fmt.Println("   or: echo <token> | jwtdec")
			os.Exit(1)
		}
		token = strings.TrimSpace(string(data))
	}

	parts := strings.Split(token, ".")
	if len(parts) != 3 {
		fmt.Println("error: invalid JWT format (expected header.payload.signature)")
		os.Exit(1)
	}

	names := []string{"Header", "Payload"}
	for i, name := range names {
		decoded, err := decodeSegment(parts[i])
		if err != nil {
			fmt.Fprintf(os.Stderr, "error decoding %s: %v\n", name, err)
			os.Exit(1)
		}

		var prettyJSON bytes.Buffer
		if err := json.Indent(&prettyJSON, decoded, "", "  "); err != nil {
			fmt.Fprintf(os.Stderr, "error formatting %s JSON: %v\n", name, err)
			os.Exit(1)
		}

		fmt.Printf("=== %s ===\n%s\n\n", name, prettyJSON.String())
	}

	fmt.Printf("=== Signature ===\n%s\n", parts[2])
}

func decodeSegment(s string) ([]byte, error) {
	switch len(s) % 4 {
	case 2:
		s += "=="
	case 3:
		s += "="
	}
	return base64.RawURLEncoding.DecodeString(s)
}

小结

用 OpenCode 开发这个 JWT 解析器的实际体验:

| 对比维度 | 传统方式 | OpenCode 方式 |
|---------|---------|-------------|
| 编写代码 | 查文档、手写、调错,约 20-30 分钟 | 口述需求,约 4 分钟 |
| 记住 API | 需要记住 Base64URL / json.Indent 用法 | 描述意图即可 |
| 错误处理 | 容易遗漏边界情况 | OpenCode 主动补全 |

OpenCode 最大的价值不是"替你写代码",而是让你把注意力从"怎么写"转移到"要什么"——你只需要专注于需求和逻辑,实现细节交给 AI。对于这类百行级别的小工具,效率提升是肉眼可见的 5-10 倍。

下一次接口调试再遇到 JWT,敲一行 jwtdec eyJhbG... 就够了。