首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >golang源码分析 :gopls(8)

golang源码分析 :gopls(8)

作者头像
golangLeetcode
发布2026-03-18 18:23:30
发布2026-03-18 18:23:30
600
举报

介绍完mainCommands,下面看看internalCommands,它只有一个命令:漏洞检测

代码语言:javascript
复制
type vulncheck struct {
    app *Application
}
代码语言:javascript
复制
func (v *vulncheck) Run(ctx context.Context, args ...string) error {
    if err := scan.Main(ctx, args...); err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
    return nil
}

它调用了scan.Main方法internal/vulncheck/scan/command.go

代码语言:javascript
复制
func Main(ctx context.Context, args ...string) error {
    // wrapping govulncheck.
    cmd := scan.Command(ctx, args...)
    if err := cmd.Start(); err != nil {
        return err
    }
    return cmd.Wait()
}
代码语言:javascript
复制
func Command(ctx context.Context, arg ...string) *Cmd {
    return &Cmd{
        ctx:  ctx,
        args: arg,
    }
}
代码语言:javascript
复制
type Cmd struct {
    // Stdin specifies the standard input. If provided, it is expected to be
    // the output of govulncheck -json.
    Stdin io.Reader
    // Stdout specifies the standard output. If nil, Run connects os.Stdout.
    Stdout io.Writer
    // Stderr specifies the standard error. If nil, Run connects os.Stderr.
    Stderr io.Writer
    // Env is the environment to use.
    // If Env is nil, the current environment is used.
    // As in os/exec's Cmd, only the last value in the slice for
    // each environment key is used. To specify the setting of only
    // a few variables, append to the current environment, as in:
    //
    //  opt.Env = append(os.Environ(), "GOOS=plan9", "GOARCH=386")
    //
    Env []string
    ctx  context.Context
    args []string
    done chan struct{}
    err  error
}

接着开始扫描,获取环境变量,然后启动一个goroutine调用scan方法来扫描

代码语言:javascript
复制
func (c *Cmd) Start() error {
    if c.done != nil {
        return errors.New("vuln: already started")
    }
    if c.Stdin == nil {
        c.Stdin = os.Stdin
    }
    if c.Stdout == nil {
        c.Stdout = os.Stdout
    }
    if c.Stderr == nil {
        c.Stderr = os.Stderr
    }
    if c.Env == nil {
        c.Env = os.Environ()
    }
    c.done = make(chan struct{})
    go func() {
        defer close(c.done)
        c.err = c.scan()
    }()
    return nil
}
代码语言:javascript
复制
func (c *Cmd) scan() error {
    if err := c.ctx.Err(); err != nil {
        return err
    }
    return scan.RunGovulncheck(c.ctx, c.Env, c.Stdin, c.Stdout, c.Stderr, c.args)
}

调用的是包golang.org/x/vuln/internal/scan/run.go

代码语言:javascript
复制
func RunGovulncheck(ctx context.Context, env []string, r io.Reader, stdout io.Writer, stderr io.Writer, args []string) error {
    cfg := &config{env: env}
    if err := parseFlags(cfg, stderr, args); err != nil {
        return err
    }
    client, err := client.NewClient(cfg.db, nil)
    if err != nil {
        return fmt.Errorf("creating client: %w", err)
    }
    prepareConfig(ctx, cfg, client)
    var handler govulncheck.Handler
    switch cfg.format {
    case formatJSON:
        handler = govulncheck.NewJSONHandler(stdout)
    case formatSarif:
        handler = sarif.NewHandler(stdout)
    case formatOpenVEX:
        handler = openvex.NewHandler(stdout)
    default:
        th := NewTextHandler(stdout)
        cfg.show.Update(th)
        handler = th
    }
    if err := handler.Config(&cfg.Config); err != nil {
        return err
    }
    incTelemetryFlagCounters(cfg)
    switch cfg.ScanMode {
    case govulncheck.ScanModeSource:
        dir := filepath.FromSlash(cfg.dir)
        err = runSource(ctx, handler, cfg, client, dir)
    case govulncheck.ScanModeBinary:
        err = runBinary(ctx, handler, cfg, client)
    case govulncheck.ScanModeExtract:
        return runExtract(cfg, stdout)
    case govulncheck.ScanModeQuery:
        err = runQuery(ctx, handler, cfg, client)
    case govulncheck.ScanModeConvert:
        err = govulncheck.HandleJSON(r, handler)
    }
    if err != nil {
        return err
    }
    return Flush(handler)
}

会根据不同的格式进行扫描,最后通过等待chan的返回结果来等待goroutine的运行结束

代码语言:javascript
复制
func (c *Cmd) Wait() error {
    if c.done == nil {
        return errors.New("vuln: start must be called before wait")
    }
    <-c.done
    return c.err
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档