云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

虚拟主机_百度云盘_9元

小七 141 0

构建最简单的Go静态分析工具

gonativevendoring(又称GO15VENDOREXPERIMENT)允许您通过将依赖项放在项目中的vendor文件夹中来冻结依赖关系。然后,编译器将在搜索GOPATH之前查找该路径。与使用每个项目的GOPATH相比,唯一的麻烦是,您可能会忘记提供GOPATH中的包。该程序将为您构建,但不会为其他任何人构建。回到WFM时代!我决定我想要一些东西,一个工具,来检查我所有的(非stdlib)依赖项是否都是贩卖的。起初,我考虑使用go list,Dave Cheney恰当地将其称为瑞士军刀,但尽管它可以显示整个递归依赖树(format.Deps),但无法从模板引擎知道标准库中是否存在依赖项。我们只需将每个输出传递回go list以检查.Standard,但我认为这是构建一个非常简单的静态分析工具的好时机。正如您将看到的,Go的简单性和库使它成为一项非常简单的任务。首先,加载程序我们使用golang.org/x/tools/go/loader在命令行加载作为参数传递的包,包括基于标志的测试文件。无功配置加载程序.Config对于-u,p:=范围flag.Args() {if*测试{conf.ImportWithTests(p)}其他{配置导入(p)}}程序,错误:=形态负荷()如果出错!等于零{日志。致命(错误)}对于p:=范围所有程序包{正式印刷品(p.Path())}通过这几行代码,我们已经复制了go list-f{.Deps}}!这里唯一缺少的加载功能是通配符(./…)支持。该代码在go工具源代码中,未被报告。有一个关于公开它的问题,但现在包只是复制粘贴它。我们将使用该代码的打包版本,github.com/kisielk/gotool:对于-u,p:=范围gotool.ImportPaths(flag.Args()) {最后,由于我们现在只对依赖树感兴趣,所以我们指示解析器只执行imports语句,而忽略结果"not used"错误:conf.ParserMode= parser.ImportsOnly配置允许错误=正确conf.TypeChecker.Error.错误=func(错误){}那么,实际的逻辑我们现在有一个加载程序对象,它保存对各种加载器.PackageInfo对象,这些对象又是包、AST和类型信息的组合。所有你需要做的就是进行任何复杂的分析。并不是说我们今天要这么做:)我们只需复制go-list逻辑来识别stdlib包,并从列表中删除通过命令行传递的包:首字母:=make(地图[*加载器.PackageInfo]布尔)对于-u,pi:=范围程序初始化包() {初始[pi]=真}var包[]*加载器.PackageInfo对于-u,pi:=范围所有程序包{如果是首字母[pi]{持续}如果len(pi文件)==0{继续//虚拟stdlib包}文件名:=程序集.Fset.File(pi文件[0].Pos()).Name()如果!字符串.HasPrefix(文件名,build.Default.GOROOT) ||!标准导入路径(包装路径()) {packages=追加(packages,pi)}}如果包装中有任何未打印的警告,则供应商:对于u,pi:=范围包{如果字符串。索引(包装路径(),"/vendor/")=-1{正式印刷品("[!]依赖项未出售:",包装路径())}}完成!您可以在此处找到工具:https://github.com/FiloSottile/vendorcheck进一步阅读这个由alandonovan维护的文档将告诉您关于静态分析工具的更多信息。请注意,您可能会倾向于使用go/importer和类型。进口商[From]而不是x/go/loader。别那样做。它不加载源代码,但读取compiled.a文件,这些文件可能已过时或丢失。静态分析工具会对现有的包发出"找不到包"的信息,或者更糟的是,因为这一点而导致错误的结果,这是我的一个恼火之处。如果您现在有编写静态分析工具的冲动,请知道CloudFlare Go团队正在伦敦、旧金山和新加坡招聘!