nox.im · All Snippets · All in Go

Golang Conditional Compilation With Build Tags

Sometimes we’re developing Go packages that rely on specific features and want to include or exclude certain functionality. One such example is profiling and debugging, which we likely want to exclude in release builds.

Go does not have a preprocessor like C/C++ but supports build tags. These are implemented as comments at the top of files. We can guard files we want to exclude with // +build debug. debug here can be anything. These files will be excluded by default. If we want to include them, we have to invoke go build -tags=debug.

Example, I’ll mount a profile in debug mode via debug.go:

// +build debug

package main

import (
	_ "net/http/pprof"
	"runtime"

	"github.com/go-chi/chi"
	"github.com/go-chi/chi/middleware"
)

func profiler(r *chi.Mux) {
	runtime.SetBlockProfileRate(1)
	runtime.SetMutexProfileFraction(1)
	r.Mount("/debug", middleware.Profiler())
}

The release inverts the build tag in release.go and just implements a stub.

// +build !debug

package main

import "github.com/go-chi/chi"

func profiler(r *chi.Mux) {}

My Makefile then looks as follows and requires me to build releases with make release.

default: debug

release:
	@go build -mod=vendor .

debug:
	@go build -mod=vendor -tags=debug .

Note that build tags are for building and are therefore not exposed in the runtime. This is a feature to change things up regarding CPU arch, binary inclusion and size and similar. It is not a replacement for flags regarding logging or debug modes.


Last modified on Monday, Jun 6, 2022.
Go back