CodeNebula
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 integration

Full 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