Cross-platform for any application

In the introduction, we saw that a file with a name ending in _test.go would automatically be run as part of the test phase. Go uses this naming convention for additional compiler features to provide the ability to include code for a specific platform or computer architecture. For example, a file named main_windows.go will only be included in the compilation if you are building for Microsoft Windows, and the main_darwin.go file would only be compiled for macOS (darwin is the name of the underlying operating system). Similarly, the computer architecture can be used to conditionally include source code, and so a file named main_arm.go would only be part of the build for a 32-bit ARM-based processor.

Go also supports the conditional compilation of arbitrary files through the use of build constraints (also known as build tags). These operate at a file level to determine whether a file should be included in the build. To use this functionality, a comment is placed at the top of the file before the package declaration (with an important blank line afterward):

// +build linux,!386

package myapp

Basic build tags match the platform and architecture strings used for the file naming described previously, with the addition that they can be combined and negated (using the ! character). Therefore, the preceding example will be included when compiling for Linux on a non-32-bit processor (!386). This functionality can be further extended by the use of custom tags that can be passed to the compiler. In this way, an application that has advanced features only for a Macintosh could update the file to read the following:

// +build darwin,coolstuff

package myapp

This means that, when compiling for a macOS computer, you could invoke the compiler with an extra parameter to enable this coolstuff functionality as follows: go build -tags coolstuff main.go

This level of conditional compilation means that the code is not cluttered or confusing to read—each file either is, or isn't, included when building. Often, a file that contains conditional code will be paired with another that contains the alternative implementation, such as // +build !darwin !coolstuff to provide a fallback of the preceding extra functionality (this would be compiled if not on macOS or not passing the coolstuff tag). For more information about the way that build constraints are calculated, please read the documentation: https://golang.org/pkg/go/build/.

One additional compiler feature that is very useful in native app development (but should be used with caution) is the ability to call C code directly from Go, this is known as Cgo. The following example illustrates a small Cgo program that, through importing the "C" package, is able to call C code. It also defines a small inline function that can be helpful in keeping your Go code neat if you have multiple C calls to make in a method:

package main

/*
#include <stdio.h>
#include <stdlib.h>

void print_hello(const char *name) {
printf("Hello %s! ", name);
}
*/
import "C"
import "unsafe"

func main() {
cName := C.CString("World")
C.print_hello(cName)
C.free(unsafe.Pointer(cName))
}

When this is run like a normal Go program, this will print out the message exactly as you would expect:

Running C code from a go file.

As you can see, the inline C method is part of a comment, along with the required imports, which is read by Cgo when placed immediately before import "C". Notice also that a Go string cannot be passed directly to C code, but must be converted to a CString through the "C" package. It's also possible to call Go functions from the C code that is included in the compilation. A full explanation of Cgo is outside the scope of this book, but more information can be found in the documentation at https://golang.org/cmd/cgo/.  While this is very powerful functionality, it can quickly lead to platform-specific code, so it's unwise to use this unless absolutely necessary.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.139.224