关于 go-semantic-tools
go-semantic-tools 是面向 Go 开发者和编码 Agent 的技能,介绍如何使用 gopls 等理解类型的工具检查和修改代码,避免仅靠文本搜索查找符号。
主要功能
- 01按类型查找符号引用与定义
- 02发现接口实现
- 03检查调用层级与依赖
- 04语义重命名和重构操作
- 05通过 gopls 与 go vet 诊断
适用场景
- 01修改前查找所有调用方
- 02检查接口的实现类型
- 03跨模块重命名符号
- 04审查包依赖
MCP 相关
该技能介绍在 Agent 工作流中使用 gopls MCP 服务,包括修改前查找符号引用、编辑后运行诊断,以及 go.mod 变更后的漏洞检查。它还提供 gopls MCP 设置和工具的参考资料。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ eduardo-sl/ go-agent-skills --skill go-semantic-tools安装后在 Claude Code 中输入/go-semantic-tools确认已加载。
附带文件references/mcp-and-code-actions.md
详细介绍
Go 语义工具
grep 能找到字符串;工具链能理解语义。不同类型中会重复出现方法名,接口通过隐式方式实现,而点导入会误导文本搜索。在修改共享代码之前,应通过理解类型的工具获取准确信息。
按需加载的详细参考资料:
references/mcp-and-code-actions.md—gopls mcp的设置与工具、读取/编辑循环、CLI 代码操作、构建标签注意事项。
只有在下方摘要不够用时,才读取参考文件。
0. 选择接口
| 接口 | 适用情况 |
|---|---|
gopls MCP 服务(gopls mcp,v0.20+) | 以 Agent 身份工作时——工具接受符号名称和文件路径,而非光标位置 |
| Harness 内置的 LSP 集成(如果已启用) | 已有一个位置,并希望每次编辑后都推送诊断信息时 |
gopls CLI(见下文) | 用于脚本和一次性检查;Go 团队将其记录为调试接口 |
使用 MCP 服务时,遵循其工作循环:修改定义前运行 go_symbol_references,每次编辑后运行 go_diagnostics,直到没有问题;修改 go.mod 后运行 go_vulncheck,然后只对已修改的包运行 go test。设置方法和工具列表:references/mcp-and-code-actions.md。
1. 选择工具
| 问题 | 命令 |
|---|---|
| 此符号在哪里使用? | gopls references file.go:LINE:COL |
| 此符号在哪里定义? | gopls definition file.go:LINE:COL |
| 谁实现了此接口?/此类型满足哪些接口? | gopls implementation file.go:LINE:COL |
| 哪些函数(传递地)调用了此函数? | gopls call_hierarchy file.go:LINE:COL |
| 此包的 API 包含什么? | go doc ./internal/service / go doc pkg Symbol |
| 存在哪些包/哪些包依赖其他包? | go list ./...、go list -deps、go list -json |
| 按名称查找模块中的符号 | gopls workspace_symbol Name |
| 查找某个文件中的符号 | gopls symbols file.go |
位置格式为 file.go:line:column(从 1 开始)。可通过先前的搜索或 gopls symbols 获取行/列。所有 gopls 命令都必须在模块内运行,并且需要预热的构建缓存——先运行一次 go build ./...。
2. 标准调查流程
修改函数之前
gopls references internal/service/user.go:42:6 # every call site, typed
gopls call_hierarchy internal/service/user.go:42:6
对 Process( 进行文本搜索会列出各个类型的所有 Process;references 只会返回当前这个符号的调用位置——包括通过接口和嵌入发生的使用,这是 grep 无法发现的。
梳理接口
# On the interface name: all implementations
gopls implementation internal/store/store.go:15:6
# On a method of a concrete type: interfaces it satisfies
gopls implementation internal/store/postgres/user.go:30:18
添加接口方法前先运行此命令——列出的每个实现都会因此失效。
理解依赖关系图
go list ./... # all packages
go list -f '{{.ImportPath}} -> {{join .Imports " "}}' ./... # direct edges
go list -deps ./cmd/api | grep myorg # everything a binary pulls in
go list -json ./internal/service | jq .Imports # machine-readable
用它验证分层方面的说法(“domain 不导入任何内容”),而不是相信目录名称。
探索不熟悉的 API
go doc ./internal/payments # package overview
go doc ./internal/payments Gateway # one symbol, with doc comment
go doc -all ./internal/payments # full API surface
优先使用此命令,而不是打开文件:它会展示导出的契约,不包含实现细节的干扰。
3. 语义重命名
gopls rename -w internal/service/user.go:42:6 ProcessOrder
此命令会在符号的所有引用位置重命名它——包括接口、嵌入和测试包中的引用。切勿使用查找替换来重命名标识符;字段 UserID 和局部变量 UserID 拼写相同,但它们是不同的符号。
4. 无需编辑器即可查看诊断信息
gopls check ./internal/... # type errors + analyzer findings per file
go vet ./... # the vet suite standalone
gopls check 会显示 IDE 用户看到的相同诊断信息——审查尚未在编辑器中打开的代码时运行它。
5. 重构代码操作
gopls codeaction internal/order/service.go:42:2-58:3 # list
gopls codeaction -kind=refactor.extract.function -exec -diff \
internal/order/service.go:42:2-58:3 # preview
提取(函数、方法、变量、常量、提取到新文件)、内联调用、补全结构体/switch、反转 if、移除所有调用位置中未使用的参数——每项操作都能感知类型,不像手动编辑。写入前先查看 Diff;提取和内联对注释的处理尽力而为。
6. 何时仍应使用 grep
- 字符串字面量:日志消息、SQL、配置键、错误文本。
- 注释、TODO、文档。
- 尚未通过编译的代码——gopls 需要可进行类型检查的包;grep 则可用于有错误的代码树。
- 快速检查是否存在(“这个环境变量是否在任何地方被引用?”)。
经验法则:标识符 → gopls;字面量和散文 → grep。
验证清单
- 更改任何共享符号前,先使用
gopls references(而非 grep)列出所有调用位置 - 更改接口前,先对该接口运行
gopls implementation - 使用
gopls rename -w执行重命名,绝不进行文本替换 - 使用
go list导入数据验证分层假设 - 通过
go doc探索不熟悉的包,然后再阅读实现 - 在没有编辑器的情况下进行审查时,运行
gopls check/go vet - grep 仅用于搜索字面值、注释和无法编译的代码
- 每次编辑后检查诊断信息(MCP
go_diagnostics或gopls check) - 使用匹配的
GOOS/ 构建标签查询跨平台符号