Introduction
In Go, a build tag is an identifier added to a piece of code that determines when the file should be included in a package during the build process.
Why Go build tags?
Go does not have a preprocessor, a macro system, or a #define declaration to control the inclusion of platform-specific code. So to fulfill the conditional compilation build tags are introduced in Golang.
Build tag basics
Build tags are implemented as comments and can appear in any source file( not just go files), but it must appear on the top of the file in the case of GoLang.
Note: To differentiate between the package and build tags, there must be a blank line.
Rules for adding multiple tags
(1) ‘OR’ Rule
The tags separated by space will be interpreted as OR logic. This means that the package will be included if either of the tags is present when the build command is executed.
// +build tag1 tag2
(2) ‘AND’ Rule
Comma-separated tags will be interpreted as AND logic. This means that the package will be included only if all the mentioned tags are present when the build command is executed.
// +build tag1,tag2
(3) ‘NOT’ Rule
Inverted tags will be interpreted as NOT logic. This means that the package will be included only if the mentioned tag is not present when the build command is executed.
// +build !tag2
5. Hands on
Let’s consider an example where we are working with different operating systems. Some functionalities are not there in the Linux operating system so we wrote a piece of code that will include the package according to our requirements only if the operating system is Linux else the package will be excluded from the build. At this time the real-time application of conditional compilation comes into the picture.
//go build linux
// +build linux
package systemd
import "fmt"
func systemD() {
fmt.Println("Hello from linux operating system")
}
In the above example, we have added Linux build constraints. When we perform the go build operation, either we have to explicitly pass build tags to include the package or the default operating system should be Linux else it will be excluded.
6. Separate test cases in golang using build tags
As a go developer, we run go test ./… and our whole test cases will be executed present inside the root package.
The point is that we can not distinguish between the unit test and integration test, here is where Build tags become useful. You can provide build tags for test files. The tags can then be passed to the go test command.
go test -tags=integration/unit
I have two following files in my test directory. One is integration_test.go and another is unit_test.go.
(1) Integration Test
When the chosen keyword is an integration test, I just need to add a comment on the top of my file // +build integration and run the command go test ./… -tags=integration to execute it.
//go:build integration
// +build integration
package go_test
import (
"fmt"
"testing"
)
func TestIntegration(t *testing.T) {
fmt.Println("testing:", t.Name())
}
Output
mohit.dehuliya_js@SW-LP09437 go-tags % go test -tags=integration
testing: TestIntegration
PASS
ok github/mdehuliya 1.861s
(2) Unit test:
When the chosen keyword is integration test, I just need to add a comment on the top of my file // +build unit and run the command go test ./… -tags=unit to execute it.
//go:build unit
// +build unit
package go_test
import (
"fmt"
"testing"
)
func TestUnit(t *testing.T) {
fmt.Println("testing:", t.Name())
}
Output
mohit.dehuliya_js@SW-LP09437 go-tags % go test -tags=unit
testing: TestUnit
PASS
ok github/mdehuliya 1.861s