1
0
mirror of https://github.com/golang/go synced 2024-11-23 23:30:10 -07:00

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 <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Russ Cox 2018-04-25 13:03:03 -04:00
parent 670cb7603a
commit 9ccfde6ee7
4 changed files with 54 additions and 16 deletions

View File

@ -718,10 +718,12 @@
//
// Usage:
//
// go run [build flags] [-exec xprog] gofiles... [arguments...]
// go run [build flags] [-exec xprog] package [arguments...]
//
// Run compiles and runs the main package comprising the named Go source files.
// A Go source file is defined to be a file ending in a literal ".go" suffix.
// Run compiles and runs the named main Go package.
// Typically the package is specified as a list of .go source files,
// but it may also be an import path, file system path, or pattern
// matching a single known package, as in 'go run .' or 'go run my/cmd'.
//
// By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
// If the -exec flag is given, 'go run' invokes the binary using xprog:
@ -736,6 +738,7 @@
// The exit status of Run is not the exit status of the compiled binary.
//
// For more about build flags, see 'go help build'.
// For more about specifying packages, see 'go help packages'.
//
// See also: go build.
//

View File

@ -1273,6 +1273,18 @@ func TestRunInternal(t *testing.T) {
tg.grepStderr(`testdata(\/|\\)src(\/|\\)run(\/|\\)bad\.go\:3\:8\: use of internal package not allowed`, "unexpected error for run/bad.go")
}
func TestRunPkg(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
dir := filepath.Join(tg.pwd(), "testdata")
tg.setenv("GOPATH", dir)
tg.run("run", "hello")
tg.grepStderr("hello, world", "did not find hello, world")
tg.cd(filepath.Join(dir, "src/hello"))
tg.run("run", ".")
tg.grepStderr("hello, world", "did not find hello, world")
}
func testMove(t *testing.T, vcs, url, base, config string) {
testenv.MustHaveExternalNetwork(t)

View File

@ -18,11 +18,13 @@ import (
)
var CmdRun = &base.Command{
UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]",
UsageLine: "run [build flags] [-exec xprog] package [arguments...]",
Short: "compile and run Go program",
Long: `
Run compiles and runs the main package comprising the named Go source files.
A Go source file is defined to be a file ending in a literal ".go" suffix.
Run compiles and runs the named main Go package.
Typically the package is specified as a list of .go source files,
but it may also be an import path, file system path, or pattern
matching a single known package, as in 'go run .' or 'go run my/cmd'.
By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
If the -exec flag is given, 'go run' invokes the binary using xprog:
@ -37,6 +39,7 @@ available.
The exit status of Run is not the exit status of the compiled binary.
For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'.
See also: go build.
`,
@ -62,18 +65,33 @@ func runRun(cmd *base.Command, args []string) {
for i < len(args) && strings.HasSuffix(args[i], ".go") {
i++
}
files, cmdArgs := args[:i], args[i:]
if len(files) == 0 {
var p *load.Package
if i > 0 {
files := args[:i]
for _, file := range files {
if strings.HasSuffix(file, "_test.go") {
// GoFilesPackage is going to assign this to TestGoFiles.
// Reject since it won't be part of the build.
base.Fatalf("go run: cannot run *_test.go files (%s)", file)
}
}
p = load.GoFilesPackage(files)
} else if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
pkgs := load.PackagesAndErrors(args[:1])
if len(pkgs) > 1 {
var names []string
for _, p := range pkgs {
names = append(names, p.ImportPath)
}
base.Fatalf("go run: pattern %s matches multiple packages:\n\t%s", args[0], strings.Join(names, "\n\t"))
}
p = pkgs[0]
i++
} else {
base.Fatalf("go run: no go files listed")
}
for _, file := range files {
if strings.HasSuffix(file, "_test.go") {
// GoFilesPackage is going to assign this to TestGoFiles.
// Reject since it won't be part of the build.
base.Fatalf("go run: cannot run *_test.go files (%s)", file)
}
}
p := load.GoFilesPackage(files)
cmdArgs := args[i:]
if p.Error != nil {
base.Fatalf("%s", p.Error)
}

View File

@ -0,0 +1,5 @@
package main
func main() {
println("hello, world")
}