首页 > 解决方案 > 如何从 lintcmd.Run() 获取报告

问题描述

我想使用linter.

我的基本需求模块是

    "honnef.co/go/tools/analysis/lint"
    "honnef.co/go/tools/lintcmd"
    "honnef.co/go/tools/simple"
    "honnef.co/go/tools/staticcheck"
    "honnef.co/go/tools/stylecheck"
    "honnef.co/go/tools/unused"

我用以下代码注册它:

    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()

我可以得到一些输出,例如:

hello.go:141:2: should replace loop with b = append(b, a...) (S1011)

但是我们有一个 ci/cd 系统,我们想从代码检查中获取报告,但是我在 do 之后没有找到任何获取输出的方法lin.Run(),我做了更多的挖掘,发现源代码有这样的注释:

// Run 运行所有注册的分析器并报告他们的发现。// 它总是调用 os.Exit 并且不返回。func (cmd *Command) Run() { ...}

那么,我如何从调用的函数中获取输出os.Exit

附言

google了一段时间后,有人说我可以通过重定向stdout所有代码来捕获输出,如下所示:

func captureOutput(f func()) string {
    reader, writer, err := os.Pipe()
    if err != nil {
        panic(err)
    }
    stdout := os.Stdout
    stderr := os.Stderr
    defer func() {
        os.Stdout = stdout
        os.Stderr = stderr
        log.SetOutput(os.Stderr)
    }()
    os.Stdout = writer
    os.Stderr = writer
    log.SetOutput(writer)
    out := make(chan string)
    wg := new(sync.WaitGroup)
    wg.Add(1)
    go func() {
        var buf bytes.Buffer
        wg.Done()
        io.Copy(&buf, reader)
        out <- buf.String()
    }()
    wg.Wait()
    f()
    writer.Close()
    return <-out
}

但是,当我尝试正常返回时,它运行良好,但是当我尝试调用os.Exit它时却没有。

    s := captureOutput(func() {
        fmt.Println("test fmt 1")
        os.Stderr.WriteString("test stderr 1\n")
        fmt.Println("test fmt 2")
        fmt.Println("test fmt 3")
        log.Println("test log 1")
        //os.Exit(0)
    })
    fmt.Println("s-->", s)

标签: golintercicd

解决方案


推荐阅读