A file gets a descriptive name that happens to end the same way a CPU architecture does — nothing about //go:build involved, no comment, no intent to restrict anything. On the developer's own laptop (almost always amd64 or arm64) it builds fine. Then someone builds for the "wrong" one of those two, or a CI runner with a different architecture picks it up, and the package vanishes from the build with an error that never mentions the filename at all.
$ ls metrics/
metrics_arm64.go // named for a feature, not actually arch-specific code
$ GOARCH=amd64 go build . // most laptops and CI runners are amd64
package filenamesuffixdemo
imports filenamesuffixdemo/metrics: build constraints exclude all Go files in .../metrics
$ GOARCH=arm64 go build . // works -- _arm64 in the filename silently scoped the file to arm64 onlygo build compiles a Go program and its dependencies into a single binary, statically linked by default — no runtime, interpreter, or shared library needs to be installed on the machine that runs it. Cross-compiling for a different operating system or CPU architecture requires no separate toolchain: setting the GOOS and GOARCH environment variables before go build is enough, since the Go toolchain ships the pieces needed for every supported target.
A basic build
go build compiles the current package into an executable named after the module (or module directory); -o names it explicitly.
$ go build -o myapp .
$ ./myapp // runs immediately — no separate runtime needed
$ ls -lh myapp // a single, several-MB, dependency-free binaryCross-compiling with GOOS and GOARCH
Setting these two variables before the build targets any supported combination, without installing anything extra — this is a large part of why Go is popular for building CLI tools distributed across many platforms.
$ GOOS=linux GOARCH=amd64 go build -o myapp-linux .
$ GOOS=windows GOARCH=amd64 go build -o myapp.exe .
$ GOOS=darwin GOARCH=arm64 go build -o myapp-mac-m1 .
$ go tool dist list // lists every supported GOOS/GOARCH combinationBuild tags for conditional compilation
A build tag comment at the top of a file (or a filename suffix like _linux.go) restricts that file to specific platforms or conditions, letting a single codebase have OS-specific implementations that the build automatically picks between.
//go:build linux
package config
const ConfigPath = "/etc/myapp/config.yaml"Beyond an explicit //go:build comment or a _linux.go-style OS suffix, Go also recognizes filename suffixes for every supported architecture (_amd64, _arm64, _386, and so on) completely automatically — no comment required. That's the trap above: metrics_arm64.go wasn't trying to be platform-specific, but the name alone was enough to restrict it to arm64 builds only. The fix is just to stop the filename from looking like a build constraint:
$ mv metrics/metrics_arm64.go metrics/metrics.go // drop the GOARCH-shaped suffix
$ GOARCH=amd64 go build . // now compiles everywhere
$ GOARCH=arm64 go build . // still compiles -- nothing was ever arm64-specific