go rungo run compiles a main package and runs it in one step, then throws the binary away, which is great until you need that binary to still exist. This guide builds a small Go module that runs from source, accepts an argument, and can be checked without leaving a compiled artefact behind.
The examples use the Go command reported locally as go1.26.1 on Linux amd64. The installed Debian package metadata says golang-go 2:1.22~2build1, so check your own go version rather than assuming those two version strings describe the same binary.
Allow about fifteen minutes. You need a shell and a writable working directory. No command in this guide needs sudo. The example creates files under /tmp; remove that directory when you are finished if you do not want to keep it.
Start with read-only checks. They confirm the executable is on your path and show the syntax supported by this installation:
$ command -v go
/usr/local/go/bin/go
$ go version
go version go1.26.1 linux/amd64
$ go help run
usage: go run [build flags] [-exec xprog] package [arguments...]
Your path and version may differ. The useful contract is that go run first compiles a named main package and then runs the resulting program. The package can be a list of Go files from one directory, a file-system path, an import path, or a pattern that selects one package.
Checkpoint: if go version fails, stop here. Install or repair Go using your normal system-management process before changing the example.
Use a fresh directory so the test cannot alter an existing project. This is ordinary user-level work:
$ demo_dir="$(mktemp -d /tmp/go-run-demo.XXXXXX)"
$ cd "$demo_dir"
$ go mod init example.invalid/gorun-demo
go: creating new go.mod: module example.invalid/gorun-demo
$ touch main.go
The last command creates an empty file ready for editing. Replace its contents with this complete program:
package main
import (
"flag"
"fmt"
)
func main() {
name := flag.String("name", "visitor", "name to greet")
flag.Parse()
fmt.Printf("Hello, %s!\n", *name)
}
If you are following along in an editor, save this as main.go in the directory printed by demo_dir. Do not paste the shell prompt or the surrounding HTML into the Go file.
From the module directory, use a dot to select the package in the current directory. Arguments after the package are arguments for your program, not for the Go command:
$ go run . -name Ada
Hello, Ada!
With no argument, the program uses its own default:
$ go run .
Hello, visitor!
There is no binary named a.out to find in the project afterwards. In normal use, Go builds an executable in a temporary location and runs it directly, which makes go run convenient for a quick test but not a replacement for producing a distributable artefact.
Checkpoint: both commands should print one greeting and return to the shell. If the output is different, inspect main.go and run gofmt -w main.go, then try again. gofmt changes the file, so review the diff if this is an existing project.
go run . runs in the context of the main module when module-aware mode is active. It may download a dependency required by the package and may update go.sum as part of resolving it. Those are project changes, so inspect the working tree after a run that uses external packages:
$ go list -m
example.invalid/gorun-demo
$ git status --short
The example has no external dependency, so the second command should print nothing when this directory is a Git repository with no other changes. go list -m reports the selected main module; it does not run the program.
For a one-off tool whose module you do not want mixed with the current directory, a version suffix selects module-aware execution independently of a nearby go.mod:
$ go run example.com/tool/cmd/tool@latest
This is a pattern, not a command to paste blindly. It needs a real module path and network access, and it may select a newer release than you intended. Prefer an explicit version such as @v1.2.3 when repeatability matters, and read the tool's documentation before running a downloaded program.
A successful run returns zero when the Go command completes and the child program returns zero. A compile error stops before your program even starts:
$ printf 'package main\nfunc main() {\n' > broken.go
$ go run broken.go
# command-line-arguments
./broken.go:2:15: syntax error: unexpected newline in argument list; possibly missing comma or )
$ printf 'exit status: %s\n' "$?"
exit status: 1
The exact diagnostic is version-specific. What matters is the non-zero status and the source location. The example intentionally overwrites only the temporary broken.go file. Remove it before continuing:
$ rm broken.go
$ go run . -name Ada
Hello, Ada!
Warning: do not treat the exit status from go run as if it were always the application's exit status. The manual explicitly warns that Run's status is not the compiled binary's status. If a script must distinguish build failure from application failure, compile with go build to a deliberate output path and run that binary separately.
Use go build when you need a file to deploy, inspect, sign or debug. It also includes debugger information that go run omits by default to reduce build time:
$ go build -o greeting .
$ ./greeting -name Ada
Hello, Ada!
$ file greeting
greeting: ELF 64-bit LSB pie executable, x86-64, ...
The file description varies with the toolchain and build settings. The binary is now a persistent project artefact. Remove it only after you have finished using it:
$ rm greeting
Do not run a broad cleanup such as rm -rf in an existing project. If you created this guide's temporary directory, its exact path is in demo_dir; when you are certain it contains nothing you need, leave it by changing directory elsewhere and removing that one directory:
$ cd /
$ rm -rf "$demo_dir"
This last removal is irreversible for files in that temporary directory. It does not require elevated privileges.
Setting a different GOOS or GOARCH can compile for another target, but the result may not run on the current machine. If a matching emulator named go_GOOS_GOARCH_exec is on the path, go run can use it; otherwise normal direct execution is simply unavailable for that target. Treat an emulator or execution wrapper as executable code and verify its provenance before using it.
-exec provides an explicit wrapper for the compiled temporary binary:
$ go run -exec /path/to/runner . -name Ada
Only use a wrapper you control or have reviewed. It receives the temporary binary followed by your program arguments, and it can alter environment, permissions, tracing or the observed exit status, so it is not a harmless debugging decoration.
go version and go help run match the toolchain you meant to use.go run . compiled and ran the selected main package.go build when a persistent, deployable or debuggable binary is required.