To cross-compile a Go program, simply set the GOOS and GOARCH environment variables before running go build, which tells the compiler to generate binaries for a different operating system and CPU architecture than your host machine. This process is built directly into the Go toolchain, so you do not need to install separate cross-compilers or toolchains for most standard targets.
For example, if you are developing on a Linux machine with an AMD64 processor but need to deploy a binary to a macOS system with an Apple Silicon (ARM64) chip, you would run:
GOOS=darwin GOARCH=arm64 go build -o myapp-darwin-arm64 main.go
Similarly, to compile a Windows executable from a Linux host, you would use:
GOOS=windows GOARCH=amd64 go build -o myapp.exe main.go
You can verify the available targets for your specific Go version by running go tool dist list. This command outputs a list of all supported GOOS/GOARCH combinations, such as linux/arm, freebsd/amd64, or wasm/wasm. This is particularly useful when targeting embedded devices or legacy systems.
While this method works seamlessly for pure Go code, be cautious if your project relies on CGO (C bindings). When CGO is enabled, the compiler attempts to link against C libraries on the host machine. If you are cross-compiling with CGO, you must also set CC and CXX to point to the appropriate cross-compiler toolchain for the target architecture, or disable CGO entirely by setting CGO_ENABLED=0. Disabling CGO is often the simplest approach for cross-compilation if your application does not strictly require C dependencies:
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o myapp-arm64 main.go
This produces a statically linked binary that can run on the target system without needing external C libraries. Always test the resulting binary on the actual target hardware or in a container/emulator matching the target OS and architecture to ensure runtime compatibility, especially if you are using dynamic linking or platform-specific system calls.