Go is popular for DevOps because it can produce a single executable for many OS/arch targets.
go build ./...
go build -o mytool ./cmd/mytool
GOOS=linux GOARCH=amd64 go build -o mytool-linux-amd64 ./cmd/mytool
GOOS=linux GOARCH=arm64 go build -o mytool-linux-arm64 ./cmd/mytool
GOOS=darwin GOARCH=arm64 go build -o mytool-darwin-arm64 ./cmd/mytool
GOOS=windows GOARCH=amd64 go build -o mytool-windows-amd64.exe ./cmd/mytool
go build -trimpath -buildvcs=false ./cmd/mytool
-trimpath: removes local filesystem paths from the binary.-buildvcs=false: avoids embedding VCS info (useful in hermetic CI).If you have a package variable like version.Version, you can set it:
go build -ldflags "-X example.com/myrepo/internal/version.Version=1.2.3" ./cmd/mytool
Static linking depends on CGO usage and your dependencies. A common baseline:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o mytool ./cmd/mytool
If your program requires CGO (some DNS/OS integrations, sqlite, etc.), fully static builds may not be possible without extra tooling.
Prefer a build matrix over ad-hoc scripts. For Go, it’s often:
go test ./...go test -race ./... (linux/amd64)linux/amd64, linux/arm64, darwin/arm64, windows/amd64