Nuts and Bolts Go Programming Language Lead image: © Dimitar Dimitrov, 123RF.com
© Dimitar Dimitrov, 123RF.com
 

Programming with Go

Modern Classic

The programming language Go promises long-term compatibility with the recently released Version 1. Designed for system programming, it does without trendy features and is therefore interesting for anyone allergic to hype. By Oliver Frommel

Go makes no false promises. Perhaps that is exactly what makes the language so interesting in the long term. In 2007, Robert Griesemer, Ken Thompson, and Rob Pike invented Go because they were unhappy with the existing languages for system programming. They do not pander to any of the current trends like asynchronous web programming or cloud computing; instead, they have learned from 30 years of experience with C and created a programming language capable of becoming its successor.

Like C, Go [1] shows its strengths in system programming, although the language can be deployed for almost any purpose. The language inventors are employed by Google, and Go has made its way onto the Google App Engine just like Java and Python; however, support for Go is currently in the experimental stage [2].

Future Promise

Early in 2008, Thompson completed his first experimental compiler, which generates C code. Ian Taylor started a little later with work on a Go front end for the GCC compiler. Toward the end of the year, Russ Cox joined the Go project, and the work went forward a little faster. In November 2009, the team finally presented the first public release of the Go compiler. In March 2012, version 1.0 of the compiler and the specification were released, promising compatibility with future Go releases [3]. Go is thus suitable right now for genuine software projects, not just experiments.

The declared goals of the Go project are efficient compilation, fast execution, and simple programming. Existing languages fail to combine all three, say the Go inventors. Go sets out to combine the simple programming offered by increasingly popular languages such as Python and Ruby with the efficiency and reliability of languages such as C, C++, and Java. In so doing, compilation will not take as long as Java projects, for example. Additionally, Go aims to handle dependencies between external libraries in a superior way.

Simplicity is one of the outstanding features of Go, so the language's inventors have done without many constructs. First and foremost, Go aims to have a consistent and unambiguous syntax. This cannot be said of languages such as Perl, Ruby, or Scala, which use a variety of syntactic constructs or methods for one and the same purpose.

Go is oriented on C but omits many elements that redundantly fulfill the same purpose. For example, Go uses only the Postfix variant of the increment operator ++, which sits behind the variable. At the same time, this is only a statement, not an expression that can be used downstream. Although this leads to a little more typing, it does ensure clear semantics and less confusion.

Go programs are made even more clear by borrowing from structured languages such as Pascal, Modula, and Oberon. In part, the Go syntax was realized in Newsqueak and limbo. The latter is the programming language of the Inferno operating system, which in turn is an offshoot of the Plan9 system, on which Thompson and Pike worked previously.

Clearly Formatted

For example, Go does without semicolons to complete individual statements (Figure 1). Although semicolons are part of the language specification, the parser adds them independently, the way the JavaScript specification does. For this to work, programmers need to keep to the specified style of bracketing, which states that opening brackets in a block always appear at the end of a line, not on their own at the beginning of the following line. The gofmt tool provide with the package checks for this formatting, removing the need for the programmer to do so and ensuring that Go code looks the same in all projects.

The Go website tour gives users a good first impression of the programming language.
Figure 1: The Go website tour gives users a good first impression of the programming language.

Variables are declared with the keyword var, followed by the variable name and the type, that is, opposite the order in C, C++, or Java:

var x float64

Variable names can start with any character regarded as a letter in the Unicode standard. The := operator lets you define and initialize variables in one fell swoop. The var keyword can be omitted here, as in most type specifications:

i := 1
pi := 3.142

The Go developers also had a radical clean-out when it came to loops – if you take a closer look, typically all the whiles, do untils, foreachs, and so on can be reworded. Go has only one loop: the good old for loop.

Types

From the increasing popularity of languages like Python and JavaScript, the developers deduced that a simple type system will tend to promote the popularity of a programming language. As Robert Griesemer puts it: "Clumsy type systems drive people to dynamically typed languages" [4]. However, they were not prepared to sacrifice the reliability that strongly typed languages offer. The classical compromise in Go is that strong typing is implemented with type inference – that is to say, any variable has a fixed type, but the programmer does not need to specify it if the compiler naturally understands the type.

At the same time, Go does not have a strict type hierarchy. In the view of the developers, this makes the implementation of compilers and tools more complicated and leads to endless discussions on the concrete shaping of the hierarchy. Instead, Go offers important types, such as arrays, and maps (hashes) in the language core. Pointers also exist, but more like those in Pascal (i.e., without the typical C pointer arithmetic).

Generic types made popular by C++, Java, and Python are not supported in Go, even if the developers admit they can be useful, and their implementation is not unequivocally ruled out some time in the distant future.

Nevertheless, Go does support object-oriented programming; the abstraction for this is interfaces, but the interface in Go differs from its counterparts in Java or Objective C. An interface specifies a collection of methods that implement "objects" to fulfill a certain function, without belonging to a common class.

Also, Go has no exceptions because they cause uncontrollable changes in the program flow. As an alternative, Go offers multiple return values for functions, which can use a wildcard mechanism to capture error values. Line 2 of Listing 1 shows a call to os.Create(), which at the same time returns the file handle and an error code.

Listing 1: Error Handling

01 for try := 0; try < 2; try++ {
02     file, err = os.Create(filename)
03     if err == nil {
04         return
05     }
06     if e, ok := err.(*os.PathError); ok && e.Err == syscall.ENOSPC {
07         deleteTempFiles()  // Recover some space.
08         continue
09     }
10     return
11 }

Tools

If you want to start programming in Go, you typically only need to install the compiler; the more recent Linux distributions already have it in their package management systems. To install on Ubuntu 12.04, type:

apt-get install golang

Other operating systems, including Mac and Windows, have binary distributions of the Go package.

After the installation, your hard drive will contain (depending on the processor architecture) the commands 6a, 6c, 6g, and 6l – or their counterparts with the digits 5 or 8. The 6 tools are for AMD64 processors, the 5 series are for 368 processors, and the 8 series are for ARM processors. The strange names are inherited from Plan9, which uses these digits to identify the processor architectures.

Conveniently, you don't have to worry about these details in practical terms and can instead just use the front end go. It is also worth mentioning that the compiler-generated object files with the extension .6 contain references to all modules used, which the linker then follows. This avoids the problem of having to find the appropriate libraries, in addition to the header files, and specifying them during the linker process, as is the case with C and C++. If a Go program builds, the compiler can it also link it. This means that well-known linker problems are a thing of the past. go also handles the task of makefiles.

If you installed Go correctly, you should be able to run the go command at the console:

$ go version
go version go1

If the Go installation is not automatically added to your PATH for executable files, you should point the environment variable GOROOT to the parent directory and then add $GOROOT/bin to the PATH.

Because Go programs build really fast, they are well-suited to calling scripts, with certain limitations – that is, as a kind of do-it-yourself, just-in-time compilation. The Gorun tool supports this process [5].

Advanced

Despite removing many features found in other languages, Go adds modern features desired by programmers, such as closures, which in Go are anonymous functions that save their environment.

Go achieves its stated objective of simple programming for multicore systems (Go was developed in the pre-cloud era when multicore processors were the holy grail) with an abstraction called Goroutines, which follows the communicating sequential processes (CSP) model to facilitate error-prone programming with threads [6].

For further reading, check out the online document "Effective Go," which shows some "idiomatic" Go solutions [7]. A variety of books on Go have been published, and more help is available on the golang-nuts mailing list (the golang-dev list is intended for compiler developers). Finally, a tip for your web search for Go resources: Instead of typing "go" as the search term, always use "golang." Locally, you can read the entire documentation in the browser if you launch the documentation server by typing

godoc -http=:8000

Go comes with a variety of libraries (Figure 2); you can find the complete list at a number of sites [8]-[10]. Larger projects implemented in Go include the Falcore web server [11] and the StatHat [12] web software.

A few of the Go packages.
Figure 2: A few of the Go packages.

Conclusions

Go is mature and, thanks to forward compatibility promised by the developers, is suitable for professional software projects. Also, the short build times are useful for large projects. Reduction in the language scope makes it relatively easy to learn and keeps third-party code easy to read, which will ultimately benefit the serviceability of any piece of software.

The price for this reduction to the essential is the absence of such features as class-based object orientation, which many programmers are accustomed to having. Go offers various features that allow object-oriented development but requires some accommodation of new concepts. Go is expected to be implemented in an increasing number of projects, especially in the area of system programming, but support on Google's App Engine could also make it interesting for use in web programming.