nox.im · All Snippets · All in Go
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.