golangtutorialAll tutorials

Golang Compilation and Execution Explained

Understand Golang compilation and execution with go run, go build, and go install, then produce and verify a reusable application binary.

Fundamentals · Lesson 8Saved in this browser. No account required.

Go can execute a temporary build, write a reusable binary, or install a command into a configured directory. This guide traces those workflows so you can choose the right command for experiments, verification, CI, and delivery.

The example supports Go 1.22 and later. It was run and built with Go 1.24.7 on Windows amd64, and the produced binary was executed successfully.

Understand what the Go command builds

The go command loads the requested packages, resolves module dependencies, compiles packages that are not already reusable from the build cache, and links a main package into an executable. A non-main package can be compiled for use by other packages but does not become a directly runnable application.

Read the official command documentation for the complete command and flag reference. The complete Go tutorial explains packages, modules, and functions before you apply the build workflow.

Three commands cover most needs:

  • go run compiles and runs a main package without leaving the application binary in your working directory.
  • go build compiles packages and writes an executable for a requested main package.
  • go install compiles and places a command in the configured binary installation directory.

All three use the build cache. The important difference is the artifact and its intended lifetime.

Run a program while developing

Save this as main.go:

package main

import (
	"fmt"
	"runtime"
)

func platform() (string, error) {
	if runtime.GOOS == "" || runtime.GOARCH == "" {
		return "", fmt.Errorf("platform: target is unavailable")
	}
	return runtime.GOOS + "/" + runtime.GOARCH, nil
}

func main() {
	target, err := platform()
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("compiled Go program")
	fmt.Printf("runtime: %s %s\n", runtime.Version(), target)
}

Run go run main.go.

Output:

compiled Go program
runtime: go1.24.7 windows/amd64

go run is convenient for development because it combines compilation and execution. It still compiles the program, so compile errors are real; it simply manages the temporary executable for you.

For module projects, prefer go run . or go run ./cmd/server over listing individual files. Package patterns include all buildable files selected for that package, while a hand-written file list can accidentally omit one. See Golang file structure for a module with a command directory.

Build and execute a durable binary

Build the same source on Windows:

go build -o hello.exe main.go
.\hello.exe

The observed binary output was:

compiled Go program
runtime: go1.24.7 windows/amd64

On macOS or Linux, choose a filename without .exe and run it with ./hello. The binary is the deployment artifact; the Go toolchain does not need to be installed merely to run an ordinary statically linked standard-library program on the matching target. C dependencies, plugins, operating-system services, and dynamic linking choices can change that deployment story.

Use -o in build scripts so the artifact path is explicit. Without it, the output name is derived from the package or directory and varies by platform conventions.

Turn the commands into a delivery workflow

Step 1: verify behavior

Run go test ./... before building. Compilation proves that types and packages fit together; tests check the behavior you asserted. The Go tools guide builds a complete pre-review loop.

Step 2: build the intended entry point

From a module with cmd/server, run:

go build -o dist/server ./cmd/server

Create the dist directory as part of a documented build task and keep generated binaries out of source control. A clean checkout should reproduce the artifact.

Step 3: record version information

Applications often inject a version or commit identifier at link time. Keep the variable in a package intended for build metadata and use -ldflags -X only with a valid string variable. Do not use a flag copied from another repository without checking its package path.

Step 4: execute the artifact in acceptance tests

Run the built binary, exercise its health endpoint or command behavior, and check its exit status. This catches packaging mistakes that a source-level unit test does not cover.

Step 5: publish the same artifact

Deploy the binary that passed acceptance instead of rebuilding from an unrecorded environment. Rebuilding can change dependencies, flags, or toolchain inputs.

Use go install for developer commands

go install puts a command in GOBIN, or in the default binary directory derived from GOPATH when GOBIN is unset. This is useful for command-line tools you want on PATH. It is less explicit than go build -o for a release pipeline because the destination comes from environment configuration.

Installing a tool at a module version, such as go install example.com/tool@version, works outside the current module dependency graph. Use an explicit version for repeatable team setup and verify the real module path from official documentation.

Cross-compile only for a known target

For a standard-library command that supports cross-compilation, set target environment values for the build process. For example, building a Windows amd64 executable from another supported host uses GOOS=windows and GOARCH=amd64 with an .exe output name. PowerShell, Command Prompt, and POSIX shells use different environment-variable syntax.

Cross-compiling changes the target of the produced binary, not the operating system currently running the build. You normally cannot execute that binary on the host unless the host supports that target. Code using C libraries may require a target C toolchain and additional configuration.

Common mistakes

Treating go run as the production artifact

go run is a development convenience, not a stable output path. Use go build -o and test the resulting file for delivery.

Building one file from a multi-file package

go build main.go selects that file. If the package needs sibling files, build the package with go build . or its package path.

Assuming a successful build proves correct behavior

Compilation checks structural correctness, not business requirements. Run tests before the build and exercise the actual binary afterward.

What next

Organize the source using the Golang file structure guide, then automate formatting and tests with essential Go tools. If this is your first program, revisit Golang Hello World before adding more packages.