mcpField
G
go-semantic-tools

go-semantic-tools

github.com/eduardo-sl开发8398 次安装2 周前更新
代码仓库

关于 go-semantic-tools

go-semantic-tools 是面向 Go 开发者和编码 Agent 的技能,介绍如何使用 gopls 等理解类型的工具检查和修改代码,避免仅靠文本搜索查找符号。

主要功能

  1. 01按类型查找符号引用与定义
  2. 02发现接口实现
  3. 03检查调用层级与依赖
  4. 04语义重命名和重构操作
  5. 05通过 gopls 与 go vet 诊断

适用场景

  1. 01修改前查找所有调用方
  2. 02检查接口的实现类型
  3. 03跨模块重命名符号
  4. 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。

验证清单

  1. 更改任何共享符号前,先使用 gopls references(而非 grep)列出所有调用位置
  2. 更改接口前,先对该接口运行 gopls implementation
  3. 使用 gopls rename -w 执行重命名,绝不进行文本替换
  4. 使用 go list 导入数据验证分层假设
  5. 通过 go doc 探索不熟悉的包,然后再阅读实现
  6. 在没有编辑器的情况下进行审查时,运行 gopls check / go vet
  7. grep 仅用于搜索字面值、注释和无法编译的代码
  8. 每次编辑后检查诊断信息(MCP go_diagnostics 或 gopls check)
  9. 使用匹配的 GOOS / 构建标签查询跨平台符号

评论

支持 Markdown