如何获取调用os.Exit的lintcmd.Run()输出的静态代码检测报告
解决方案
方案1:直接使用analysis包原生接口执行检测(最推荐)
你已经集齐了所有需要的lint.Analyzer实例,完全可以绕开lintcmd封装的、会主动退出的Run方法,直接用Go官方golang.org/x/tools/go/analysis/checker包执行检测,全程自己控制输出和返回逻辑,不会遇到强制退出的问题:
import "golang.org/x/tools/go/analysis/checker" // 你的Analyzer切片已经准备好的前提下 cfg := &checker.Config{ // 可自行配置要检测的包、输出格式等参数 } res, err := checker.Analyze(cfg, cs) if err != nil { // 处理执行错误 } // 遍历res.Diagnostics即可拿到所有检测结果,可自行格式化输出或者存入上报结构
这个方案无黑魔法,完全符合官方设计,后续维护成本最低。
方案2:拆分为子进程执行(改动最小)
如果你不想调整现有lintcmd的调用逻辑,可以把lint执行的代码单独拆分到一个独立的Go程序里,主程序通过exec.Command启动这个子进程,直接捕获子进程的全量输出:
子进程代码(单独编译为可执行文件mylinter):
// 原有注册lint、调用Run的逻辑全部放这里 func main() { var cs []*lint.Analyzer cs = append(cs, simple.Analyzers...) cs = append(cs, staticcheck.Analyzers...) cs = append(cs, stylecheck.Analyzers...) cs = append(cs, unused.Analyzer) lin := lintcmd.NewCommand("test") lin.AddAnalyzers(cs...) lin.Run() }
主进程调用逻辑:
import "os/exec" func getLintResult() (string, error) { cmd := exec.Command("./mylinter", "你要检测的包路径") output, err := cmd.CombinedOutput() return string(output), err }
子进程调用os.Exit只会结束子进程本身,主进程不受影响,也能完整拿到所有输出内容。
方案3:劫持os.Exit(不推荐生产环境使用)
如果只是临时使用,可以通过猴子补丁的方式替换os.Exit实现,让Run调用退出的时候不会真的终止整个进程,不过这种方式依赖Go的内部实现,版本兼容性差,生产环境不建议使用。
内容的提问来源于stack exchange,提问作者Frank AK
相关产品推荐
相关产品推荐

