Skip to content

Commit 9ccfde6

Browse files
committed
cmd/go: add support for 'go run pkg' or 'go run .'
To date, go run has required a list of .go files. This CL allows in place of that list a single import path or a directory name or a pattern matching a single patckage. This allows 'go run pkg' or 'go run dir', most importantly 'go run .'. The discussion in #22726 gives more motivation. The basic idea is that you can already run 'go test .' but if you're developing a command it's pretty awkward to iterate at the same speed. This lets you do that, by using 'go run . [args]'. Fixes #22726. Change-Id: Ibfc8172a4f752588ad96df0a6b0928e9b61fa27f Reviewed-on: https://go-review.googlesource.com/109341 Run-TryBot: Russ Cox <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]>
1 parent 670cb76 commit 9ccfde6

File tree

4 files changed

+54
-16
lines changed

4 files changed

+54
-16
lines changed

src/cmd/go/alldocs.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -718,10 +718,12 @@
718718
//
719719
// Usage:
720720
//
721-
// go run [build flags] [-exec xprog] gofiles... [arguments...]
721+
// go run [build flags] [-exec xprog] package [arguments...]
722722
//
723-
// Run compiles and runs the main package comprising the named Go source files.
724-
// A Go source file is defined to be a file ending in a literal ".go" suffix.
723+
// Run compiles and runs the named main Go package.
724+
// Typically the package is specified as a list of .go source files,
725+
// but it may also be an import path, file system path, or pattern
726+
// matching a single known package, as in 'go run .' or 'go run my/cmd'.
725727
//
726728
// By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
727729
// If the -exec flag is given, 'go run' invokes the binary using xprog:
@@ -736,6 +738,7 @@
736738
// The exit status of Run is not the exit status of the compiled binary.
737739
//
738740
// For more about build flags, see 'go help build'.
741+
// For more about specifying packages, see 'go help packages'.
739742
//
740743
// See also: go build.
741744
//

src/cmd/go/go_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,18 @@ func TestRunInternal(t *testing.T) {
12731273
tg.grepStderr(`testdata(\/|\\)src(\/|\\)run(\/|\\)bad\.go\:3\:8\: use of internal package not allowed`, "unexpected error for run/bad.go")
12741274
}
12751275

1276+
func TestRunPkg(t *testing.T) {
1277+
tg := testgo(t)
1278+
defer tg.cleanup()
1279+
dir := filepath.Join(tg.pwd(), "testdata")
1280+
tg.setenv("GOPATH", dir)
1281+
tg.run("run", "hello")
1282+
tg.grepStderr("hello, world", "did not find hello, world")
1283+
tg.cd(filepath.Join(dir, "src/hello"))
1284+
tg.run("run", ".")
1285+
tg.grepStderr("hello, world", "did not find hello, world")
1286+
}
1287+
12761288
func testMove(t *testing.T, vcs, url, base, config string) {
12771289
testenv.MustHaveExternalNetwork(t)
12781290

src/cmd/go/internal/run/run.go

+31-13
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ import (
1818
)
1919

2020
var CmdRun = &base.Command{
21-
UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]",
21+
UsageLine: "run [build flags] [-exec xprog] package [arguments...]",
2222
Short: "compile and run Go program",
2323
Long: `
24-
Run compiles and runs the main package comprising the named Go source files.
25-
A Go source file is defined to be a file ending in a literal ".go" suffix.
24+
Run compiles and runs the named main Go package.
25+
Typically the package is specified as a list of .go source files,
26+
but it may also be an import path, file system path, or pattern
27+
matching a single known package, as in 'go run .' or 'go run my/cmd'.
2628
2729
By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
2830
If the -exec flag is given, 'go run' invokes the binary using xprog:
@@ -37,6 +39,7 @@ available.
3739
The exit status of Run is not the exit status of the compiled binary.
3840
3941
For more about build flags, see 'go help build'.
42+
For more about specifying packages, see 'go help packages'.
4043
4144
See also: go build.
4245
`,
@@ -62,18 +65,33 @@ func runRun(cmd *base.Command, args []string) {
6265
for i < len(args) && strings.HasSuffix(args[i], ".go") {
6366
i++
6467
}
65-
files, cmdArgs := args[:i], args[i:]
66-
if len(files) == 0 {
67-
base.Fatalf("go run: no go files listed")
68-
}
69-
for _, file := range files {
70-
if strings.HasSuffix(file, "_test.go") {
71-
// GoFilesPackage is going to assign this to TestGoFiles.
72-
// Reject since it won't be part of the build.
73-
base.Fatalf("go run: cannot run *_test.go files (%s)", file)
68+
var p *load.Package
69+
if i > 0 {
70+
files := args[:i]
71+
for _, file := range files {
72+
if strings.HasSuffix(file, "_test.go") {
73+
// GoFilesPackage is going to assign this to TestGoFiles.
74+
// Reject since it won't be part of the build.
75+
base.Fatalf("go run: cannot run *_test.go files (%s)", file)
76+
}
77+
}
78+
p = load.GoFilesPackage(files)
79+
} else if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
80+
pkgs := load.PackagesAndErrors(args[:1])
81+
if len(pkgs) > 1 {
82+
var names []string
83+
for _, p := range pkgs {
84+
names = append(names, p.ImportPath)
85+
}
86+
base.Fatalf("go run: pattern %s matches multiple packages:\n\t%s", args[0], strings.Join(names, "\n\t"))
7487
}
88+
p = pkgs[0]
89+
i++
90+
} else {
91+
base.Fatalf("go run: no go files listed")
7592
}
76-
p := load.GoFilesPackage(files)
93+
cmdArgs := args[i:]
94+
7795
if p.Error != nil {
7896
base.Fatalf("%s", p.Error)
7997
}
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package main
2+
3+
func main() {
4+
println("hello, world")
5+
}

0 commit comments

Comments
 (0)