Go Interface Lens

一个面向大型 Go 工程的 VS Code / Cursor 接口导航扩展。它在接口、接口方法和具体实现之间提供双向 CodeLens,同时使用按查询的声明搜索和按需 AST 校验兼顾响应速度与查找准确性。
不依赖 gopls;激活和 CodeLens 渲染期间不扫描 workspace,导航数据全部按需构建。
工程特色
快速启动,按需精确查找
- 激活和 CodeLens 展示只解析当前编辑器文档,不建立 workspace 索引,也不启动 AST Worker。
- 点击 CodeLens 后先解析目标所在包,再由 ripgrep 按方法声明搜索文件内容,仅加载命中的完整包。
- ripgrep 命中的文件会先按目标方法的入参和出参数量粗筛,数量不符的同名声明不会触发完整包加载。
- 候选包中的类型别名和嵌入关系会按需递归扩展;Tree-sitter 最终校验完整方法集和签名,不会把普通函数调用当成声明。
- 每个接口只选择一个较长的方法名作为候选锚点,避免为完整方法集重复扫描 workspace 和模块缓存。
- 已完成的查询直接使用内存缓存,未变化的文件可从持久化 AST 缓存恢复。
Tree-sitter Go WASM 精确解析
扩展使用 Microsoft 维护的 @vscode/tree-sitter-wasm 0.3.1 和 Tree-sitter Go grammar,
不再包含自写 Go lexer 或语法解析器,也不通过 VS Code LSP API 或 gopls 查询实现。
每次解析都以单个 .go 文件为输入,提取紧凑的声明 IR 后立即释放 Tree-sitter Tree。
当前支持:
- Go 的隐式接口实现和完整方法签名校验。
- 值接收者、指针接收者及其不同的方法集。
- 本地或跨包嵌入的 struct、interface 和类型别名。
- 标准库接口、
go.mod 锁定依赖中的接口与具体实现、local replace、module replace 和 GOROOT 源码。
- workspace 与锁定依赖中的正反向关系均在点击后按当前目标计算,不建立整库关系表。
- 锁定依赖候选按接口中的单个方法锚点收窄,仅加载命中的包;跨包 alias、embed 和方法位置在同一次查询上下文中解析。
- AST 缓存按 pack 合并读取;未变化的 workspace 和依赖声明可跨重启复用,但查询结果不会持久化为整库关系快照。
- import 别名、包内别名、跨包别名链和复合别名。
byte/uint8、rune/int32、any/interface{} 等价关系,并尊重包级同名声明遮蔽。
- 多行声明、分组参数、泛型接口与实现、泛型嵌入、泛型实例、匿名接口和嵌套函数类型。
- 泛型接口会跨完整方法集统一推导类型实参,并校验可解析的接口方法集约束;支持多个类型参数及其在复合类型中的嵌套、重复使用。
- 类型参数约束支持精确类型项、
~T、union、comparable、具名约束和依赖其他类型参数的约束;只能作为约束使用的接口本身仍不会显示 CodeLens。
- 指针、切片、数组、map、可变参数、channel、包限定类型和 Unicode 参数名的签名归一化。
- Go build tags、GOOS/GOARCH 文件约束和未保存编辑内容。
双向导航
implementations
type UserRepository interface {
→ implementations
FindByID(ctx context.Context, id string) (*User, error)
→ implementations
Save(ctx context.Context, user *User) error
}
← goto interface
func (r *PostgresUserRepository) FindByID(
ctx context.Context,
id string,
) (*User, error) {
// ...
}
implementations:查看完整实现该接口的类型,并跳转到类型声明。
→ implementations:查看某个接口方法的实现,并跳转到具体方法。
← goto interface:从接收者方法反向查找匹配的接口。
为大型工程控制开销
- 候选包 AST 使用 1-32 个 Worker Thread 并发解析,默认上限为 32,并按可用 CPU 和内存自适应收缩。
- 锁定依赖目录会轮询分配给一个全局共享的 ripgrep 进程池;进程数最多为 16,并按扩展进程可用 CPU 自动收缩。接口声明、实现声明和类型引用搜索共享该上限,每个进程继续使用 ripgrep 自身的自动线程数;单根 workspace 搜索仍使用单进程。
- workspace 候选包最多同时加载 8 个;每个选中包最多并发读取 16 个源码文件。两者只作用于已被声明搜索命中的包,不会全量读取 workspace。
- Tree-sitter 解析前会清空函数体内容,仅保留函数签名、原始行号和源码偏移。
- 相同文件的并发解析请求会自动合并。
- 依赖接口只在工作区查找不到结果时按需搜索,不全量索引 module cache。
- 外部依赖中的 concrete type 不会混入工作区实现结果。
- 文件监听、未保存 overlay 和查询结果都支持增量失效。
- 支持 multi-root workspace,并保持同名包、同名接口和同名类型相互隔离。
VSIX 从锁定的上游版本原样携带 Tree-sitter JavaScript runtime、核心 runtime
WASM、Go grammar WASM 和 MIT 许可证;依赖包里的其他语言 grammar 不会打进扩展。
使用方法
查看接口实现
- 打开包含 Go interface 的文件。
- 在
type InterfaceName interface 上方点击 implementations。
- 在 Quick Pick 中选择目标实现。
- 编辑器会跳转到对应 struct 或类型声明。
查看接口方法实现
- 打开包含 Go interface 的文件。
- 在目标方法上方点击
→ implementations。
- 选择具体实现。
- 编辑器会直接跳转到该方法的声明位置。
从实现跳转到接口
- 打开带接收者方法的 Go 文件,例如
func (s *Service) Run()。
- 点击方法上方的
← goto interface。
- 选择匹配的接口。
- 编辑器会跳转到接口声明。
查找结果会自动排除配置中的 mock、测试、生成文件和其他不需要的类型。
查询完成后会释放依赖源码文本;多余 AST Worker 在空闲超时后收缩到一个,供后续查询复用。
环境要求
- VS Code 1.76+,或兼容 VS Code 扩展的 Cursor 版本。
- 使用
.go 文件;Go module 工程可以获得最完整的跨包和依赖解析能力。
- 实现匹配不依赖 gopls。解析 GOROOT 或 module cache 中的源码时,需要本机存在相应 Go 源码或依赖缓存。
配置
打开 VS Code / Cursor 设置并搜索 Go Interface Lens,或直接编辑 settings.json。
| 配置项 |
默认值 |
作用 |
goInterfaceLens.astConcurrency |
32 |
候选包 AST Worker 上限,可设置为 1-32;实际并发按可用 CPU 和内存自适应 |
goInterfaceLens.excludedFolders |
mocks, mock, testdata, vendor |
按目录路径排除候选加载和 Tree-sitter 解析;支持 *、? 通配符 |
goInterfaceLens.excludedFilePatterns |
_mock.go, mock_, .pb.go, _test.go |
排除文件名中包含指定文本的文件 |
goInterfaceLens.excludedTypePatterns |
Mock, mock, Stub, Fake |
排除名称中包含指定文本的类型 |
goInterfaceLens.excludedPackagePatterns |
空 |
按 Go import path 排除工作区候选包和依赖解析;* 匹配任意字符(包括 /),? 匹配单个字符 |
goInterfaceLens.searchDependencies |
true |
正反向导航时按需搜索 go.mod 锁定依赖中的接口与具体实现;无锁信息时仅搜索显式配置的依赖根 |
goInterfaceLens.goModCache |
空 |
手动指定 Go module cache;为空时自动探测 |
修改包路径排除规则后,插件会自动清理查询缓存;下一次导航查询会按新规则重新搜索,无需重启扩展。
示例:
{
"goInterfaceLens.astConcurrency": 32,
"goInterfaceLens.searchDependencies": true,
"goInterfaceLens.goModCache": "",
"goInterfaceLens.excludedPackagePatterns": [
"code.byted.org/overpass*"
],
"goInterfaceLens.excludedFolders": [
"mocks",
"mock",
"testdata",
"vendor",
"generated",
"*overpass*"
],
"goInterfaceLens.excludedFilePatterns": [
"_mock.go",
"mock_",
".pb.go",
"_test.go",
".gen.go"
],
"goInterfaceLens.excludedTypePatterns": [
"Mock",
"mock",
"Stub",
"Fake"
]
}
AST Worker 使用 os.availableParallelism() 感知宿主机或容器可用 CPU,并结合 cgroup 内存余量限制并发。扩展启动时 Worker 数为 0,首次导航查询才创建,空闲后收缩到 1。
类型名以 _ 开头时始终从实现结果中排除。
性能基线
开发环境中的合成测试包含 402 个 Go 文件:
- workspace 根注册约
0.1ms,读取 Go 源码数和 Tree-sitter WASM 解析文件数均为 0。
- 首次按需查询约
90ms。
- 缓存查询约
0ms。
- 一次稀有方法查询只解析 2 个候选文件。
实际耗时取决于工程规模、磁盘、文件系统类型和候选方法的常见程度。
命令
| 命令 |
作用 |
Go: Show Implementations |
查看接口的完整实现 |
Go: Show Method Implementations |
查看接口方法实现 |
Go: Goto Interface |
从接收者方法跳转到接口 |
Go: Clear Implementation Lens Cache |
清除 AST 和查询缓存 |
前三个命令通常由对应 CodeLens 携带上下文调用。清理缓存命令可以直接从 Command Palette 执行。
常见问题
看不到 CodeLens
确认文件语言模式是 Go,且扩展已在当前本地或远程扩展宿主中启用。
在工作区 settings.json 中显式启用 Go 文件的 CodeLens:
{
"[go]": {
"editor.codeLens": true
}
}
确认接口本身不含 ~int | ~string 之类只能用于类型约束的类型集合;带类型参数但方法集可在运行时使用的泛型接口支持 CodeLens。
执行 Developer: Reload Window。
查看 Output -> Go Interface Lens 和 Extension Host 日志。
[go].editor.codeLens 是 VS Code 兼容编辑器提供的 Go 语言模式设置,控制所有注册到 Go 文件的 CodeLens provider,并不表示本扩展依赖 Go 扩展或 gopls。即使工作区中没有这项配置,Trae、Cursor、远程设置、用户 Profile 或语言级配置也可能改变它的最终生效值;显式设为 true 可以避免这些配置层级关闭本扩展的 CodeLens。
CodeLens 显示较慢
VS Code 会并发请求同一 Go 文件上所有匹配的 CodeLens provider,并在编辑器侧合并结果后统一展示。Go Interface Lens 自己不调用 Go 扩展或 gopls,但官方 Go 扩展也是一个并列的 provider;当它等待 gopls 初始化或分析时,合并阶段可能延迟,本扩展已经生成的 CodeLens 也会稍后才显示或变为可点击。标准 CodeLens API 不提供 provider 优先级或独立渲染能力,因此本扩展无法绕过编辑器的聚合等待。
如果主要使用 Go Interface Lens 完成接口导航,推荐在设置中搜索 Go: Enable Code Lens(go.enableCodeLens),关闭官方 Go 扩展不需要的 CodeLens 总开关或子项,同时保留:
{
"[go]": {
"editor.codeLens": true
}
}
这样只是不再让官方 Go CodeLens 参与聚合,不会关闭本扩展,也不会禁用 gopls 的补全、诊断和普通代码跳转。不同版本的 Go 扩展可能将该设置显示为一个总开关或 references、run test 等多个子项,可以按实际需要全部关闭。
找不到实现
- 确认实现具有接口要求的全部方法及一致的参数、返回值类型。
- 检查值接收者和指针接收者的方法集差异。
- 检查排除目录、文件和类型配置。
- 执行
Go: Clear Implementation Lens Cache 后重试。
依赖中的接口或实现找不到
- 确认
goInterfaceLens.searchDependencies 为 true。
- 确认依赖出现在
go.mod 中,或配置了有效 replace。
- 必要时通过
goInterfaceLens.goModCache 指定 module cache 的绝对路径。
License
MIT
版本记录见 CHANGELOG.md。问题反馈请提交到 GitHub Issues。