Google Go Lets Developers Work More With Multicore, Parallel Computing

Google Go includes support for multicore, asynchronous programming, modern functional programming and closures. How do these features stack up to other modern languages? Our reviewer finds out.

In January 2010, I reviewed the new language called Google Go for eWEEK. In that review, I focused mainly on the syntax of the language. Since then, the language has changed and evolved, culminating (finally) this year with Release 1.0 on March 28 and release 1.0.3 Sept. 24.

And over the past few months there have been a few minor releases to fix a few problems, which means now is a good time to take it for another spin and see how it has grown up.

Go and Multicore Programming

One thing I took a hard look at this time was concurrency. Much of today's Web-based software needs to be able to handle high volumes of users. Concurrency is a must. To run some concurrency tests with Google Go, I used an Intel second-generation Core i7 processor with four cores, each with two threads, for eight virtual CPUs. A quick Google search for concurrency issues in Go shows some people complaining that their programs run slower. However, this was not the case when I tested Go for the second time.

Remember, parallel programming isn't easy, and it's not something where you just turn up the number of cores and let it rip. You have to carefully design your algorithms to work in parallel. And if they're not designed right, there's a good possibility you'll see little or no increase in performance or even a decrease in performance. The algorithms may end up running sequentially, and then add on the overhead of trying to split them up among cores, and the whole thing will take longer to run.

To handle concurrency, Go includes what Google calls “goroutines,” which are similar to the coroutines in other languages. But an important feature of goroutines is that they don't just provide yield and resume. You can also easily communicate between them using variables called channels.

You can certainly communicate between parallel routines in other languages, as well, but Go makes this easy to do so. However, this does add to the work you need to do in writing your code. Channels effectively work as shared variables, but synchronization is built in. And there lies possible trouble: If you have a single channel variable and, say, eight computing threads, each running on a virtual core, and you force threads to wait as one is using the channel, then you totally defeat the parallelism.

I was able to easily put together some code that demonstrated this problem. Therefore, it's important to understand how parallel algorithms work and how to make use of parallel concepts like reduction.

Nevertheless, using goroutines, you can effectively create a parallel loop. If you're familiar with the Cilk Plus extensions to C++, you'll note that this is similar to the Cilk_for loop. However, in Cilk Plus you simply write your loop like a normal C++ loop and the runtime decides how and when to perform the parallelism, and how to divide it among cores. In Go, there's not a parallel for loop built into the syntax, but you can easily spawn parallel threads for them like so:

for i := 0; i<30; i++ {

go func(i2 int) {




However, they don't automatically run on multiple cores. But it's easy to add multicores with a single line of code:


This tells the Go runtime to use eight logical cores. When I tested this out, I put a tight loop inside the parallel function and, as expected, all eight cores of my machine spun. (During this, I'm using Microsoft Windows and Task Manager, which shows the eight cores maxing out.) You can determine the number of cores with runtime.NumCPU():