Google’s Go—A Scalable Programming Language

Computing-wise, we live in a concurrent world. Or at least we should. Most of us, however, find writing concurrent code easier said than done. Our machines sport multiple cores, but how many are actually being used?

Let me put this another way: Does the code you write scale automatically to multiple cores? With the effects of Moore’s Law leveling off, we can't ignore the issue much longer, as Herb Sutter points out in his article, “The Free Lunch Is Over.” 

Many of the languages in widespread use today came out of the chute without any thought for concurrency, which then had to be bolted on after the fact. For the most part, that meant adding a threading library. Threads are fine in many contexts (pardon the pun), but their sidekicks, locks, don’t scale well.

Languages like Python and Ruby suffer from the Global Interpreter Lock (GIL), rendering CPU-bound concurrency essentially impossible with threads. Python’s solution to the GIL dilemma is to use multiple processes that communicate via message passing, also known as the Actor model of concurrency, which is supported in languages such as Erlang, Scala, and D. Actors finesse locks’ lack of composability while incurring a little bit of housekeeping overhead.

The language most in demand at the moment, according to tiobe.com, is C, although it occasionally trades places with Java for the top spot. C’s success has resulted in large part because of its ability to allow access to hardware with a reasonable level of readability and portability. But C was designed for single-processor machines with relatively simple architectures.

Which brings me to your favorite modern language that you’re not using: Google’s Go.

Go is a lightweight, systems programming language designed with concurrency, scalability, and the web in mind. It received Tiobe’s Language of the Year Award in 2009 but has seen little use since it was still in beta, which for Google means it’s practically ready for prime time :-). It has now been officially released and will be supported by Google for the foreseeable future, so there’s no need to be shy. Here’s the obligatory “word count” example in Go:

package main
import (
    "fmt"
    "strings"
)
func WordCount(s string) map[string]int {
    m := make(map[string]int)
    for _,w := range strings.Fields(s) {
        _, ok := m[w]
        if ok {
            m[w] += 1
        } else {
            m[w] = 1
        }
    }
    return m
}
func main() {
    fmt.Println(WordCount("I don't think that word means what he thinks it means"))
}
/* Output:
map[don't:1 word:1 what:1 thinks:1 think:1 it:1 means:2 he:1 that:1 I:1]
*/

As you can see, Go uses C-style syntax—to a degree. With good line alignment, semicolons are inferred at the end of each statement. The variable m refers to a string-to-int map. The fields.Strings function yields a list of strings split by whitespace from its input string.

Go is garbage collected yet compiles to native code, just like the D language. As far as OOP is concerned, Go supports interfaces, objects, and polymorphism—but without classes(!).

It uses “channels”—an abstraction in the spirit of queues and pipes—to communicate between “goroutines” (concurrency-enabled functions). How goroutines are distributed among your machine’s resources is not specified, leaving an implementation to do the right thing for your platform now and in the future.

While Go supports locks, it encourages using channels instead. In fact, the Go community has coined a slogan: “Do not communicate by sharing memory; instead, share memory by communicating.”

You can find tutorials and code examples in abundance online at golang.org.  

About the Author

TechWell Insights To Go

(* Required fields)

Get the latest stories delivered to your inbox every week.