Background
We are developing a project that needs to run on Windows and Linux. The project is written in Golang. There are a lot of codes that can be shared between these OS, so we decided to make it in the same project. By this way we can speed up the development process very much.
In the project, there are some code files that run on Windows only, some run on Linux only, and some run on both Windows and Linux. And we want to separating them on build. It means:
- The binary for Linux will contain common code + code for Linux
- The binary for Windows will contain common code + code for Windows
Benefit
By separating files on build, I can see that we have some benefits:
- We don't have to check runtime.GOOS to determine which code will run and which will not. We can write less code to do the same thing.
- Changes for Linux environment will not affect the behaviors on Windows and vice versa. So it help us reduce time for testing.
- The test code will be built and run on the specified OS only, so we get a more accurate code coverage percentage.
How can we do it
Firstly we need to divide the code for Linux and for Windows into different files. After that we can use one of the following ways.
Name the file
We can tell go
what OS and what architecture we want to build a file by naming it. The followings are examples about file names and build behaviors:
-
hello_windows.go
,hello_windows_test.go
: will only be built and tested on Windows -
hello_linux.go
,hello_linux_test.go
: will only be built and tested on Linux -
hello_linux_adm64.go
,hello_linux_adm64_test.go
: will only be built and tested on Linux 64 bit
The file name patterns are:
-
*_GOOS.go
,*_GOOS_test.go
-
*_GOOS_GOARCH.go
,*_GOOS_GOARCH_test.go
We can do this way if the build condition is only about OS and architecture.
Use // +build
command
This way gives us more control on the environment. We can specify multiple OS and architectures, compiler, go version, -tags
// file name: hello.go
// +build linux windows
// +build amd64
package hello
The comment // +build
above will tell go
to build the file on Windows 64bit or Linux 64 bit. So when we build the project in freebsd
, the package hello
will be excluded from the files to be built.
If we have a test for this package, it will be something like this:
// file name: hello_test.go
// +build linux windows
// +build amd64
package hello
The comment // +build
above will tell go
to exclude this file from test on environments that are not Linux 64bit or Windows 64bit for us. We don't have to check the OS then skip the test.
For complex usage of // +build
, please check golang documentation here: https://golang.org/cmd/go/#hdr-Build_constraints