CHAPTER 2
Whether you’re an experienced programmer or a novice, you’re going to love Go.
Go was conceived and born at Google in 2007, when three veteran engineers (Robert Griesemer, Rob Pike, and Ken Thompson) got together to build the language they wanted to use for systems programming. Google is a unique company, and the problems it faces are unique. With an untold number of computers, all networked together and running on different platforms and being developed in many different programming languages, no systems programming task is trivial at Google.
The rationale behind Go was to create a programming language that could be used to build robust and hugely scalable software, abstracting away some of the complexity of working in an environment using more traditional programming languages. Many people, myself included, really enjoy programming in Go, but the idea was that even if it you didn’t fall in love with the language, you could at least appreciate the sensible design decisions that went into it. Creating Go was never about pushing completely new paradigms in programming language design; it was all about building a great language for the sort of challenges programmers face today.
So what challenges did these engineers identify, and how were those met by Go?
Even though computers are much faster these days, software builds for many programmers are still painfully slow. With Go, you can compile a substantial program in just a few seconds on a single computer. Everything compiles to a single binary file. There is no interpreter (like Python’s or JavaScript’s) and no reliance on a runtime environment like Java’s JVM.
Managing dependencies is a huge issue for programmers today, and the old “header file” approach of languages such as C++ just doesn’t scale very well. As programs have grown in size, working out when dependencies are no longer required has become very difficult.
Go’s dependency management is baked into the language itself. If a package is listed as a dependency and no code within the program uses it, the Go compiler raises an error and no further compilation occurs until the dependency is removed. This guarantees that there are never any unwanted dependencies and keeps the code base lean. Go also builds dependent packages before the packages that depend on them, leading to much faster compilation because only a single file is opened by the compiler when an import occurs.
“Hold on!” I hear you say. “Isn’t there a big backlash against static typing in so-called ’modern’ dynamically-typed languages like JavaScript and Python?”
Well yes, but dynamic typing comes with its own problems. With a statically typed language such as C++ or Java, you must specify the type of the data stored by a variable. The compiler checks variable assignments in your program and shouts at you if you’re trying to store data of one type in a variable that only supports data of a different type. This can help weed out a lot of silly errors early on and avoid some painful debugging later. But advocates of dynamically typed languages applaud the flexibility and speed of development. Go offers the best of both worlds: it is statically typed, but features of the language make it appear to have some of the benefits of a dynamically typed language.
Concurrency means executing multiple routines simultaneously in order to speed up processing and offload effort. It’s the way to make use of all those extra resources in the multicore CPUs that are ubiquitous nowadays. In many programming languages, concurrency is an afterthought and difficult to do well. Go provides great support for concurrent programming with Goroutines and channels.
Unlike many compiled languages, you don’t have to manage memory yourself. This has often been the cause of very hard-to-debug memory leaks that gradually bring systems to a halt. C and C++ are notorious for this: mismanaged memory leads to memory leaks, which are difficult to debug and will eventually bring your application to a standstill. Go manages memory for you. When resources are no longer required, Go’s garbage collector gets rid of them and releases the memory back to the system.
Programmers will argue day and night about the best way to format code. With Go, there is no need to argue about the virtue of tabs versus spaces or different commenting styles because the Go guidelines make clear which way Go thinks you should do it. There’s even a tool that will take your code and format it, Go-style, for you. All of the examples in this course have been run through the Go formatter. You can either call it explicitly, or, in most IDEs and editors, you can configure it to execute every time you save the file you are working on.
Go comes with many other out-of-the-box tools for documentation, testing, maintenance, and all the other time-consuming tasks that programmers must deal with.
Google uses of C-style syntax, making it easy for anyone with experience of programming in other C-style languages such as Java, C#, and JavaScript to learn Go.
In short, Go is a modern programming language built to deal with modern programming challenges. It is small, easy to learn, and hugely powerful. However, it’s not ideal for every type of project. Let’s look at what Go is good at and where it is less useful.
Go is good for:
Go is not so great at:
Now that we know a bit about the rationale behind Go and its strengths and weaknesses, let’s talk about the language itself.