Go 分析框架:由 Go 团队提供的模块化静态分析
Go 分析框架:由 Go 团队提供的模块化静态分析
概览
Go 分析框架定义了一个通用的 Analyzer 接口,使开发者能够编写可被 vet、文本编辑器、构建系统和自定义 linter 使用的模块化静态分析。
分析器类型
分析器静态描述一个分析函数。它包括用于名称、文档、标志集、Run 函数、RunDespiteErrors、ResultType、Requires 依赖和 FactTypes 的字段。Run 函数接收一个 *Pass 并返回一个 interface{} 结果和一个错误。Validate 函数检查 Requires 图是否无环,事实和结果类型是否唯一,并且 Run 不为 nil。
Pass 类型
Pass 表示一个工作单元:将一个 Analyzer 应用于一个 Go 包。它提供文件集、语法树、类型信息以及用于报告诊断的辅助方法。ResultOf 映射保存来自所需分析器的结果。Reportf 和 ReportRangef 辅助函数创建带有位置、可选类别和消息的 Diagnostic 对象。Pass 还提供 ExportObjectFact、ImportObjectFact、ExportPackageFact 和 ImportPackageFact,用于在包之间共享事实。
事实和模块化分析
事实是分析可以附加到 types.Object 或包上的中间、可序列化的信息片段。它们使得可以进行独立编译风格的分析:一个分析器可以导出事实,随后的分析器(即使在不同的地址空间)可以通过驱动程序导入这些事实。事实类型必须是指针,并使用 gob 进行编码;它们应该是无状态且确定的,以便与内容可寻址缓存一起工作。printf 检查器通过记录哪些函数委托给 fmt.Printf 并重用该事实来检查其他包中的调用来演示这一点。
测试 Analyzer
analysistest 子包通过在 testdata 文件上运行 Analyzer 并通过源代码中的 "// want" 注释验证预期的诊断和事实来帮助测试 Analyzer。这提供了一种轻量级的方法,无需构建完整的驱动程序即可断言正确性。
独立命令
singlechecker 和 multichecker 子包简化了创建运行一个或多个分析器的命令行工具。典型的单分析器命令如下:
package main
import ( "golang.org/x/tools/go/analysis/passes/findcall" "golang.org/x/tools/go/analysis/singlechecker" )
func main() { singlechecker.Main(findcall.Analyzer) }
多检查器命令仅需将 *Analyzer 的切片传递给 multichecker.Main。
生态系统使用
评论者指出,该框架已经被许多 linter 使用(参见 golang.org/x/tools/go/analysis 的导入图)。一位用户报告称,为 SpiceDB 定义自定义分析器取得了成功,强调该框架减少了对部落知识的需求并加快了代码审查。另一位评论者询问这些原语是否可用于构建更广泛的架构 linter,表明对更高级别检查的兴趣。进一步的评论者赞赏 Go 团队在人类和代理开发两方面对工具的关注,引用了利用构建标签和 testscript 进行有针对性测试的个人项目。
这些观察表明,分析包既是现有工具(如 vet)的可重用基础,也是用户定义的检查器的基础,支持在 Go 生态系统中进行模块化、事实驱动的静态分析。