internal/govulncheck: change Run to return Result struct

The function signature for Run is changed to:

func Run(ctx context.Context, cfg Config) (*Result, error) {...}

At the moment, Result is an empty struct. Fields will be added in
subsequent CLs.

For golang/go#56042

Change-Id: I4568ca8147809c0c4e26aa83c96440d16ca32ffb
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/439075
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Reviewed-by: Julie Qiu <julieqiu@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/cmd/govulncheck/main.go b/cmd/govulncheck/main.go
index f4bfadf..3ece7fa 100644
--- a/cmd/govulncheck/main.go
+++ b/cmd/govulncheck/main.go
@@ -76,7 +76,7 @@
 	}
 
 	ctx := context.Background()
-	err := govulncheck.Run(ctx, govulncheck.Config{
+	_, err := govulncheck.Run(ctx, govulncheck.Config{
 		AnalysisType: mode,
 		OutputType:   outputType,
 		Patterns:     patterns,
diff --git a/exp/govulncheck/govulncheck.go b/exp/govulncheck/govulncheck.go
index 4e38003..ed52a93 100644
--- a/exp/govulncheck/govulncheck.go
+++ b/exp/govulncheck/govulncheck.go
@@ -17,5 +17,6 @@
 // Main is the main function for the govulncheck command line tool.
 func Main(cfg Config) error {
 	ctx := context.Background()
-	return govulncheck.Run(ctx, cfg)
+	_, err := govulncheck.Run(ctx, cfg)
+	return err
 }
diff --git a/internal/govulncheck/result.go b/internal/govulncheck/result.go
new file mode 100644
index 0000000..16b2359
--- /dev/null
+++ b/internal/govulncheck/result.go
@@ -0,0 +1,10 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package govulncheck
+
+// Result is contains output information for govulncheck.
+//
+// TODO(https://go.dev/issue/56042): this API is a work in progress.
+type Result struct {
+}
diff --git a/internal/govulncheck/run.go b/internal/govulncheck/run.go
index d4e7296..1292cdd 100644
--- a/internal/govulncheck/run.go
+++ b/internal/govulncheck/run.go
@@ -21,7 +21,7 @@
 )
 
 // Run is the main function for the govulncheck command line tool.
-func Run(ctx context.Context, cfg Config) error {
+func Run(ctx context.Context, cfg Config) (*Result, error) {
 	dbs := []string{vulndbHost}
 	if db := os.Getenv(envGOVULNDB); db != "" {
 		dbs = strings.Split(db, ",")
@@ -30,7 +30,7 @@
 		HTTPCache: DefaultCache(),
 	})
 	if err != nil {
-		return err
+		return nil, err
 	}
 	vcfg := &vulncheck.Config{Client: dbClient, SourceGoVersion: internal.GoVersion()}
 
@@ -47,27 +47,27 @@
 	case AnalysisTypeBinary:
 		f, err := os.Open(cfg.Patterns[0])
 		if err != nil {
-			return err
+			return nil, err
 		}
 		defer f.Close()
 		r, err = binary(ctx, f, vcfg)
 		if err != nil {
-			return err
+			return nil, err
 		}
 	case AnalysisTypeSource:
 		pkgs, err = loadPackages(cfg)
 		if err != nil {
 			// Try to provide a meaningful and actionable error message.
 			if !fileExists(filepath.Join(cfg.SourceLoadConfig.Dir, "go.mod")) {
-				return ErrNoGoMod
+				return nil, ErrNoGoMod
 			}
 			if !fileExists(filepath.Join(cfg.SourceLoadConfig.Dir, "go.sum")) {
-				return ErrNoGoSum
+				return nil, ErrNoGoSum
 			}
 			if isGoVersionMismatchError(err) {
-				return fmt.Errorf("%v\n\n%v", ErrGoVersionMismatch, err)
+				return nil, fmt.Errorf("%v\n\n%v", ErrGoVersionMismatch, err)
 			}
-			return err
+			return nil, err
 		}
 
 		// Sort pkgs so that the PkgNodes returned by vulncheck.Source will be
@@ -75,33 +75,39 @@
 		sortPackages(pkgs)
 		r, err = vulncheck.Source(ctx, pkgs, vcfg)
 		if err != nil {
-			return err
+			return nil, err
 		}
 		unaffected = filterUnaffected(r)
 		r.Vulns = filterCalled(r)
 	default:
-		return fmt.Errorf("%w: %s", ErrInvalidAnalysisType, cfg.AnalysisType)
+		return nil, fmt.Errorf("%w: %s", ErrInvalidAnalysisType, cfg.AnalysisType)
 	}
 
 	switch cfg.OutputType {
 	case OutputTypeJSON:
 		// Following golang.org/x/tools/go/analysis/singlechecker,
 		// return 0 exit code in -json mode.
-		return writeJSON(r)
+		if err := writeJSON(r); err != nil {
+			return nil, err
+		}
+		return &Result{}, nil
 	case OutputTypeText, OutputTypeVerbose:
 		// set of top-level packages, used to find representative symbols
 		ci := getCallInfo(r, pkgs)
 		writeText(r, ci, unaffected, cfg.OutputType == OutputTypeVerbose)
 	case OutputTypeSummary:
 		ci := getCallInfo(r, pkgs)
-		return writeJSON(summary(ci, unaffected))
+		if err := writeJSON(summary(ci, unaffected)); err != nil {
+			return nil, err
+		}
+		return &Result{}, nil
 	default:
-		return fmt.Errorf("%w: %s", ErrInvalidOutputType, cfg.OutputType)
+		return nil, fmt.Errorf("%w: %s", ErrInvalidOutputType, cfg.OutputType)
 	}
 	if len(r.Vulns) > 0 {
-		return ErrContainsVulnerabilties
+		return nil, ErrContainsVulnerabilties
 	}
-	return nil
+	return &Result{}, nil
 }
 
 func writeJSON(r any) error {