Go🚀Advancedadvanced
Build Tags and Conditional Compilation
Go · Advanced · Run with go run
Explanation
Build tags (also called build constraints) control which files are included in a build. The `//go:build` directive at the top of a file specifies conditions: OS (`linux`, `windows`, `darwin`), architecture (`amd64`, `arm64`), Go version (`go1.21`), or custom tags. This enables platform-specific implementations without `#ifdef`.
Real-World Scenario
A file system watcher has separate implementations per OS: `watcher_linux.go` uses `inotify`, `watcher_darwin.go` uses `kqueue`, `watcher_windows.go` uses `ReadDirectoryChangesW`. Go selects the right file based on `GOOS` automatically.
Quick Snippet
snippet.go
// File: signal_unix.go
//go:build linux || darwin || freebsd
package main
import (
"os/signal"
"syscall"
)
func listenForSignals() {
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT)
<-ch
}
// File: signal_windows.go
//go:build windows
package main
func listenForSignals() {
// Windows-specific implementation
}
// Custom tags: go build -tags integration
//go:build integrationFull Example
build_tags.go
// Compile: go run build_tags.go
// Output (value depends on your OS):
// running on: <linux|darwin|windows>
// build tag form shown in comments below
//
// Build tags select which files compile. A file starting with:
//
// //go:build linux || darwin
//
// is only included when GOOS matches. Custom tags work too:
//
// //go:build integration → go build -tags integration
//
// At runtime, the portable alternative is the `runtime` package.
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("running on:", runtime.GOOS)
fmt.Println("architecture:", runtime.GOARCH)
}
Run command
go run build_tags.go