Build tags are part of the conditional compilation system provided by the go tool. This is a quick post to discuss using build tags to selectively enable debug printing in a package.
This afternoon I merged a contribution to pkg/sftp which improved the packet encoding performance but introduced a bug where some packet types were incorrectly encoded.
% go test -integration Unknown message 0 ... oops
Turning on verbose got a little closer.
% go test -integration -v === RUN TestUnmarshalAttrs --- PASS: TestUnmarshalAttrs (0.00s) === RUN TestNewClient --- PASS: TestNewClient (0.00s) === RUN TestClientLstat Unknown message 0
But each integration test sends many different packets, which one was at fault?
Rather than reaching for fmt.Println I took a few minutes to add conditional debugging to this package.
debug.go
// +build debug
package sftp
import "log"
func debug(fmt string, args ...interface{}) {
	log.Printf(fmt, args...)
}
release.go
// +build !debug
package sftp
func debug(fmt string, args ...interface{}) {}
Adding a call to debug inside sendPacket it was easy to figure out the packet which was being incorrectly encoded.
% go test -tags debug -integration -v -run=Lstat 2014/09/28 11:18:31 send packet sftp.sshFxInitPacket, len: 38 === RUN TestClientLstat 2014/09/28 11:18:31 send packet sftp.sshFxInitPacket, len: 5 2014/09/28 11:18:31 send packet sftp.sshFxpLstatPacket, len: 62 Unknown message 0
Debugging is optional
When I committed the fix for this bug I didn’t have to spend any time removing the debug function calls inside the package.
When -tags debug is not present, the version from release.go, effectively a no-op, is used.
Extra credit
This package includes integration tests which are not run by default. How the -integration test flag works is left as an exercise to the reader.