.NET

Getting Going with Go

By Mark Summerfield, August 07, 2012

The first installment in our five-week tutorial on Google's new native language explains how to set up Go and build programs. It then walks through code examples that highlight some of the language's interesting features.

Compiling and Linking

Two steps are required to build Go programs: compiling and linking. (Since we are assuming the use of the gc compiler, readers using gccgo will need to follow the compile and link process described in golang.org/doc/gccgo_install.html. Similarly, readers using other compilers will need to compile and link as per their compiler's instructions.) Both compiling and linking are handled by the go tool, which can not only build local programs and packages, but can also fetch, build, and install third-party programs and packages.

For the go tool to be able to build local programs and packages, there are three requirements. First, the Go bin directory ($GOROOT/bin or %GOROOT%\bin) must be in the path. Second, there must be a directory tree that has an src directory and under which the source code for the local programs and packages resides. For example, the examples unpack to goeg/src/hello, goeg/src/bigdigits, and so on. Third, the directory above the src directory must be in the GOPATH environment variable. For example, to build the hello example using the go tool, we must do this:

$ export GOPATH=$HOME/goeg
$ cd $GOPATH/src/hello
$ go build

In both cases we assume that PATH includes $GOROOT/bin or %GOROOT%\bin. Once the go tool has built the program, we can run it. By default the executable is given the same name as the directory it is in (e.g., hello on Unix-like systems and hello.exe on Windows). Once built, we can run the program in the usual way.

$ ./hello
Hello World!

Note that we do not need to compile—or even explicitly link—any other packages (even though as we will see, hello.go uses three standard library packages). This is another reason why Go programs build so quickly.

If we have several Go programs, it would be convenient if all their executables could be in a single directory that we could add to our PATH. Fortunately, the go tool supports this as follows:

$ export GOPATH=$HOME/goeg
$ cd $GOPATH/src/hello
$ go install

The go install command does the same as go build only it puts the executable in a standard location ($GOPATH/bin or %GOPATH%\bin). This means that by adding a single PATH ($GOPATH/bin or %GOPATH>%\bin) to our PATH, all Go programs that we install will conveniently be in the PATH.

In addition to the examples given here, we are likely to want to develop our own Go programs and packages in our own directory. This can easily be accommodated by setting the GOPATH environment variable to two (or more) colon-separated paths (semicolon-separated on Windows).

Although Go uses the go tool as its standard build tool, it is perfectly possible to use make or some of the modern build tools, or to use alternative Go-specific build tools, or add-ons for popular IDEs.

Hello Who?

Now that we have seen how to build the hello program we will look at its source code. Here is the complete hello program (in file hello/hello.go):

Go uses C++-style comments: // for single-line comments that finish at the end of the line and /* ... */ for comments that can span multiple lines. It is conventional in Go to mostly use single-line comments, with spanning comments often used for commenting out chunks of code during development.

Every piece of Go code exists inside a package, and every Go program must have a main package with a main() function that serves as the program's entry point, that is, the function that is executed first.) In fact, Go packages may also have init() functions that are executed before main().) Notice that there is no conflict between the name of the package and the name of the function.

Go operates in terms of packages rather than files. This means that we can split a package across as many files as we like, and from Go's point of view, if they all have the same package declaration, they are all part of the same package and no different than if all their contents were in a single file. Naturally, we can also break our applications' functionality into as many local packages as we like, to keep everything neatly modularized.

The import statement imports three packages from the standard library. The fmt package provides functions for formatting text and for reading formatted text, the os package provides platform-independent operating-system variables and functions, and the strings package provides functions for manipulating strings.

Go's fundamental types support the usual operators (for example, + for numeric addition and for string concatenation), and the Go standard library supplements these by providing packages of functions for working with the fundamental types, such as the strings package imported here. It is also possible to create our own custom types based on the fundamental types and to provide our own methods—that is, custom type-specific functions—for them.

The reader may have noticed that the program has no semicolons, that the imports are not comma-separated, and that the if statement's condition does not require parentheses. In Go, blocks, including function bodies and control structure bodies (so, for if statements and for loops), are delimited using braces. Indentation is used purely to improve human readability. Technically, Go statements are separated by semicolons, but these are inserted by the compiler, so we don't have to use them ourselves unless we want to put multiple statements on the same line. No semicolons and fewer commas and parentheses give Go programs a lighter look and require less typing.

Go functions and methods are defined using the func keyword. The main package's main() function always has the same signature—it takes no arguments and returns nothing. When main.main() finishes the program will terminate and return 0 to the operating system. Naturally, we can exit whenever we like and return our own choice of value.

The first statement in the main() function (using the := operator) is called a short variable declaration in Go terminology. Such a statement both declares and initializes a variable at the same time. Furthermore, we don't need to specify the variable's type because Go can deduce that from the initializing value. So in this case we have declared a variable called who of type string, and thanks to Go's strong typing we may only assign strings to who.

The os.Args variable is a slice of strings. Go makes use of arrays, slices, and other collection data types but for these examples it is sufficient to know that a slice's length can be determined using the built-in len() function and its elements can be accessed using the [] index operator using a subset of the Python syntax. In particular, slice[n] returns the slice's nth element (counting from zero), and slice[n:] returns another slice which has the elements from the nth element to the last element. In the collections chapter we will see the full generality of Go's syntax in this area. In the case of os.Args, the slice should always have at least one string (the program's name), at index position 0. (All Go indexing is zero-based.)

If the user has entered one or more command-line arguments the if condition is satisfied and we set the who string to contain all the arguments joined up as a single string. In this case, we use the assignment operator (=), since if we used the short variable declaration operator (:=) we would end up declaring and initializing a newwho variable whose scope was limited to the if statement's block. The strings.Join() function takes a slice of strings and a separator (which could be empty, that is, ""), and returns a single string consisting of all the slice's strings with the separator between each one. Here we have joined them using a single space between each.

Finally, in the last statement, we print Hello, a space, the string held in the who variable, and a newline. The fmt package has many different print variants, some like fmt.Println() which will neatly print whatever they are given, and others like fmt.Printf() that use placeholders to provide very fine control over formatting.

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task.
However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

This month's Dr. Dobb's Journal

This month,
Dr. Dobb's Journal is devoted to mobile programming. We introduce you to Apple's new Swift programming language, discuss the perils of being the third-most-popular mobile platform, revisit SQLite on Android
, and much more!